summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/-ext-/array/test_to_ary_concat.rb20
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb1
-rw-r--r--test/-ext-/float/test_nextafter.rb2
-rw-r--r--test/-ext-/string/test_capacity.rb37
-rw-r--r--test/-ext-/string/test_rb_str_dup.rb6
-rw-r--r--test/-ext-/wait/test_wait.rb16
-rw-r--r--test/bigdecimal/test_bigdecimal.rb6
-rw-r--r--test/bigdecimal/test_ractor.rb2
-rw-r--r--test/coverage/test_coverage.rb146
-rw-r--r--test/csv/interface/test_read.rb32
-rw-r--r--test/csv/interface/test_read_write.rb9
-rw-r--r--test/csv/interface/test_write.rb34
-rw-r--r--test/csv/parse/test_invalid.rb13
-rw-r--r--test/date/test_date_strftime.rb2
-rw-r--r--test/did_you_mean/spell_checking/test_pattern_key_name_check.rb20
-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/did_you_mean/tree_spell/test_change_word.rb2
-rw-r--r--test/drb/drbtest.rb6
-rw-r--r--test/error_highlight/test_error_highlight.rb164
-rw-r--r--test/excludes/TestArray.rb1
-rw-r--r--test/fiber/scheduler.rb38
-rw-r--r--test/fiber/test_io.rb43
-rw-r--r--test/fiber/test_thread.rb39
-rw-r--r--test/fiddle/helper.rb20
-rw-r--r--test/fiddle/test_c_struct_builder.rb33
-rw-r--r--test/fiddle/test_cparser.rb2
-rw-r--r--test/fiddle/test_func.rb25
-rw-r--r--test/fiddle/test_function.rb36
-rw-r--r--test/fiddle/test_handle.rb11
-rw-r--r--test/fiddle/test_memory_view.rb8
-rw-r--r--test/fiddle/test_pointer.rb21
-rw-r--r--test/fileutils/test_fileutils.rb2
-rw-r--r--test/io/console/test_io_console.rb2
-rw-r--r--test/irb/test_cmd.rb24
-rw-r--r--test/irb/test_color.rb2
-rw-r--r--test/irb/test_color_printer.rb2
-rw-r--r--test/irb/test_completion.rb37
-rw-r--r--test/irb/test_context.rb79
-rw-r--r--test/irb/test_raise_no_backtrace_exception.rb6
-rw-r--r--test/irb/test_ruby_lex.rb46
-rw-r--r--test/irb/test_workspace.rb21
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb69
-rw-r--r--test/lib/jit_support.rb1
-rw-r--r--test/logger/helper.rb13
-rw-r--r--test/logger/test_logdevice.rb2
-rw-r--r--test/logger/test_logger.rb2
-rw-r--r--test/logger/test_logperiod.rb2
-rw-r--r--test/logger/test_severity.rb2
-rw-r--r--test/mkmf/test_have_var.rb17
-rw-r--r--test/net/http/test_httpresponse.rb2
-rw-r--r--test/objspace/test_objspace.rb4
-rw-r--r--test/openssl/test_bn.rb4
-rw-r--r--test/openssl/test_config.rb16
-rw-r--r--test/openssl/test_digest.rb2
-rw-r--r--test/openssl/test_pair.rb3
-rw-r--r--test/openssl/test_pkcs12.rb297
-rw-r--r--test/openssl/test_pkey.rb27
-rw-r--r--test/openssl/test_pkey_dh.rb8
-rw-r--r--test/openssl/test_pkey_dsa.rb15
-rw-r--r--test/openssl/test_pkey_ec.rb17
-rw-r--r--test/openssl/test_pkey_rsa.rb33
-rw-r--r--test/openssl/test_ssl.rb141
-rw-r--r--test/openssl/test_ssl_session.rb8
-rw-r--r--test/openssl/test_ts.rb18
-rw-r--r--test/openssl/utils.rb49
-rw-r--r--test/optparse/test_did_you_mean.rb8
-rw-r--r--test/ostruct/test_ostruct.rb12
-rw-r--r--test/pathname/test_pathname.rb30
-rw-r--r--test/pathname/test_ractor.rb2
-rw-r--r--test/psych/test_scalar_scanner.rb49
-rw-r--r--test/psych/test_string.rb13
-rw-r--r--test/racc/assets/mof.y6
-rw-r--r--test/racc/case.rb (renamed from test/racc/helper.rb)7
-rw-r--r--test/racc/regress/mof6
-rw-r--r--test/racc/test_chk_y.rb2
-rw-r--r--test/racc/test_grammar_file_parser.rb2
-rw-r--r--test/racc/test_racc_command.rb2
-rw-r--r--test/racc/test_scan_y.rb2
-rw-r--r--test/rdoc/support/test_case.rb17
-rw-r--r--test/rdoc/test_rdoc_any_method.rb48
-rw-r--r--test/rdoc/test_rdoc_cross_reference.rb2
-rw-r--r--test/rdoc/test_rdoc_generator_darkfish.rb24
-rw-r--r--test/rdoc/test_rdoc_generator_json_index.rb2
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb2
-rw-r--r--test/rdoc/test_rdoc_options.rb73
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb66
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb58
-rw-r--r--test/rdoc/test_rdoc_servlet.rb4
-rw-r--r--test/rdoc/test_rdoc_text.rb10
-rw-r--r--test/readline/test_readline.rb111
-rw-r--r--test/reline/helper.rb3
-rw-r--r--test/reline/test_key_actor_emacs.rb22
-rw-r--r--test/reline/test_key_actor_vi.rb30
-rw-r--r--test/reline/test_key_stroke.rb32
-rw-r--r--test/reline/test_reline.rb69
-rw-r--r--test/reline/test_reline_key.rb53
-rw-r--r--test/reline/test_terminfo.rb8
-rw-r--r--test/reline/test_unicode.rb5
-rw-r--r--test/reline/windows/test_key_event_record.rb2
-rwxr-xr-xtest/reline/yamatanooroti/multiline_repl107
-rw-r--r--test/reline/yamatanooroti/termination_checker.rb2
-rw-r--r--test/reline/yamatanooroti/test_rendering.rb439
-rw-r--r--test/ripper/test_ripper.rb9
-rw-r--r--test/ripper/test_sexp.rb14
-rw-r--r--test/ruby/enc/test_emoji_breaks.rb8
-rw-r--r--test/ruby/test_argf.rb19
-rw-r--r--test/ruby/test_array.rb30
-rw-r--r--test/ruby/test_ast.rb17
-rw-r--r--test/ruby/test_autoload.rb27
-rw-r--r--test/ruby/test_backtrace.rb28
-rw-r--r--test/ruby/test_class.rb18
-rw-r--r--test/ruby/test_enum.rb4
-rw-r--r--test/ruby/test_enumerator.rb2
-rw-r--r--test/ruby/test_env.rb14
-rw-r--r--test/ruby/test_exception.rb3
-rw-r--r--test/ruby/test_file_exhaustive.rb20
-rw-r--r--test/ruby/test_gc_compact.rb5
-rw-r--r--test/ruby/test_hash.rb18
-rw-r--r--test/ruby/test_integer.rb2
-rw-r--r--test/ruby/test_io.rb12
-rw-r--r--test/ruby/test_iseq.rb10
-rw-r--r--test/ruby/test_jit.rb31
-rw-r--r--test/ruby/test_keyword.rb17
-rw-r--r--test/ruby/test_literal.rb35
-rw-r--r--test/ruby/test_m17n.rb4
-rw-r--r--test/ruby/test_marshal.rb106
-rw-r--r--test/ruby/test_method.rb4
-rw-r--r--test/ruby/test_module.rb70
-rw-r--r--test/ruby/test_numeric.rb8
-rw-r--r--test/ruby/test_objectspace.rb2
-rw-r--r--test/ruby/test_optimization.rb58
-rw-r--r--test/ruby/test_pack.rb30
-rw-r--r--test/ruby/test_parse.rb12
-rw-r--r--test/ruby/test_pattern_matching.rb160
-rw-r--r--test/ruby/test_process.rb107
-rw-r--r--test/ruby/test_refinement.rb121
-rw-r--r--test/ruby/test_regexp.rb62
-rw-r--r--test/ruby/test_require.rb69
-rw-r--r--test/ruby/test_rubyoptions.rb26
-rw-r--r--test/ruby/test_rubyvm.rb53
-rw-r--r--test/ruby/test_settracefunc.rb68
-rw-r--r--test/ruby/test_string.rb12
-rw-r--r--test/ruby/test_syntax.rb33
-rw-r--r--test/ruby/test_thread.rb8
-rw-r--r--test/ruby/test_thread_cv.rb3
-rw-r--r--test/ruby/test_time.rb5
-rw-r--r--test/ruby/test_yjit.rb634
-rw-r--r--test/rubygems/bogussources.rb9
-rw-r--r--test/rubygems/helper.rb24
-rw-r--r--test/rubygems/private_ec_key.pem9
-rw-r--r--test/rubygems/test_gem.rb497
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb67
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb25
-rw-r--r--test/rubygems/test_gem_installer.rb2
-rw-r--r--test/rubygems/test_gem_package.rb53
-rw-r--r--test/rubygems/test_gem_path_support.rb8
-rw-r--r--test/rubygems/test_gem_platform.rb1
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb30
-rw-r--r--test/rubygems/test_gem_request.rb44
-rw-r--r--test/rubygems/test_gem_resolver_installer_set.rb18
-rw-r--r--test/rubygems/test_gem_security.rb36
-rw-r--r--test/rubygems/test_gem_source_fetch_problem.rb10
-rw-r--r--test/rubygems/test_gem_specification.rb460
-rw-r--r--test/rubygems/test_gem_uri.rb39
-rw-r--r--test/rubygems/test_rubygems.rb44
-rw-r--r--test/runner.rb2
-rw-r--r--test/socket/test_addrinfo.rb2
-rw-r--r--test/socket/test_basicsocket.rb2
-rw-r--r--test/test_ipaddr.rb59
-rw-r--r--test/test_timeout.rb11
-rw-r--r--test/uri/test_http.rb31
-rw-r--r--test/zlib/test_zlib.rb4
173 files changed, 5222 insertions, 1385 deletions
diff --git a/test/-ext-/array/test_to_ary_concat.rb b/test/-ext-/array/test_to_ary_concat.rb
new file mode 100644
index 00000000000..feb1bc11096
--- /dev/null
+++ b/test/-ext-/array/test_to_ary_concat.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: false
+require 'test/unit'
+require '-test-/array/to_ary_concat'
+
+class TestConcatStress < Test::Unit::TestCase
+ def setup
+ @stress_level = GC.stress
+ GC.stress = true
+ end
+
+ def teardown
+ GC.stress = @stress_level
+ end
+
+ def test_concat
+ arr = [nil]
+ bar = Bug::Bar.new
+ arr.concat(bar)
+ end
+end
diff --git a/test/-ext-/bug_reporter/test_bug_reporter.rb b/test/-ext-/bug_reporter/test_bug_reporter.rb
index ac6d92bb67f..759e295fb62 100644
--- a/test/-ext-/bug_reporter/test_bug_reporter.rb
+++ b/test/-ext-/bug_reporter/test_bug_reporter.rb
@@ -8,6 +8,7 @@ class TestBugReporter < Test::Unit::TestCase
description = RUBY_DESCRIPTION
description = description.sub(/\+JIT /, '') if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ description = description.sub(/\+YJIT /, '') if defined?(YJIT.enabled?) && YJIT.enabled?
expected_stderr = [
:*,
/\[BUG\]\sSegmentation\sfault.*\n/,
diff --git a/test/-ext-/float/test_nextafter.rb b/test/-ext-/float/test_nextafter.rb
index 636f803fac8..e0a76935b16 100644
--- a/test/-ext-/float/test_nextafter.rb
+++ b/test/-ext-/float/test_nextafter.rb
@@ -50,7 +50,7 @@ class TestFloatExt < Test::Unit::TestCase
assert_equal(s1, s2,
"Bug::Float.missing_nextafter(#{'%a' % n1}, #{'%a' % n2}) = #{'%a' % v1} != " +
"#{'%a' % v2} = Bug::Float.system_nextafter(#{'%a' % n1}, #{'%a' % n2})")
- rescue Minitest::Assertion
+ rescue Test::Unit::AssertionFailedError
if /aix/ =~ RUBY_PLATFORM
skip "Known bug in nextafter(3) on AIX"
end
diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb
index df59e767781..583c98fca46 100644
--- a/test/-ext-/string/test_capacity.rb
+++ b/test/-ext-/string/test_capacity.rb
@@ -4,13 +4,10 @@ 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[:RVALUE_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
@@ -18,7 +15,8 @@ class Test_StringCapacity < Test::Unit::TestCase
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
@@ -39,7 +37,10 @@ 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
@@ -51,9 +52,27 @@ class Test_StringCapacity < Test::Unit::TestCase
end
def test_capacity_fstring
- s = String.new("I am testing", capacity: 1000)
+ s = String.new("a" * max_embed_len, capacity: 1000)
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
+ if GC.using_rvargc?
+ 2 * RbConfig::SIZEOF['void*'] + RbConfig::SIZEOF['short']
+ else
+ 2 * RbConfig::SIZEOF['void*']
+ end
+ 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_rb_str_dup.rb b/test/-ext-/string/test_rb_str_dup.rb
index 49b6af9598d..c76a90252f7 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-/wait/test_wait.rb b/test/-ext-/wait/test_wait.rb
index 79127c041b5..8e53f067cf3 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/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 99f92c461c5..49e6b2a70e1 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -146,6 +146,7 @@ class TestBigDecimal < Test::Unit::TestCase
def test_BigDecimal_with_float
assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))
assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4))
+ assert_equal(BigDecimal("0.01"), BigDecimal(0.01, Float::DIG + 1))
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) }
@@ -656,13 +657,10 @@ class TestBigDecimal < Test::Unit::TestCase
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
+ Warning[:deprecated] = true if defined?(Warning.[])
BigDecimal("1").precs
end
- ensure
- Warning[:deprecated] = saved
end
def test_precs
diff --git a/test/bigdecimal/test_ractor.rb b/test/bigdecimal/test_ractor.rb
index f78663f15e2..798cc494e18 100644
--- a/test/bigdecimal/test_ractor.rb
+++ b/test/bigdecimal/test_ractor.rb
@@ -6,7 +6,7 @@ class TestBigDecimalRactor < Test::Unit::TestCase
def setup
super
- skip unless defined? Ractor
+ omit unless defined? Ractor
end
def test_ractor_shareable
diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb
index 22557bd9d8b..882368363a8 100644
--- a/test/coverage/test_coverage.rb
+++ b/test/coverage/test_coverage.rb
@@ -774,4 +774,150 @@ 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
+
+ cov1 = "[0, 0, nil, nil, 0, 1, nil, nil, 0, 0, nil]"
+ cov2 = "[0, 0, nil, nil, 0, 1, nil, nil, 0, 1, nil]"
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], [])
+ Coverage.setup
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ p Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ p Coverage.result[tmp + "/test.rb"]
+ end;
+
+ 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}}"
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], [])
+ Coverage.setup(:all)
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ p Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ p Coverage.result[tmp + "/test.rb"]
+ end;
+
+ cov1 = "{:oneshot_lines=>[6]}"
+ cov2 = "{:oneshot_lines=>[6, 10]}"
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], [])
+ Coverage.setup(oneshot_lines: true)
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ p Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ p Coverage.result[tmp + "/test.rb"]
+ end;
+ }
+ }
+ end
+
+ def test_coverage_state
+ assert_in_out_err(%w[-rcoverage], <<-"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(%w[-rcoverage], <<-"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(%w[-rcoverage], <<-"end;", ["{}"], [])
+ Coverage.setup
+ p Coverage.result
+ end;
+ end
+
+ def test_result_after_suspend
+ assert_in_out_err(%w[-rcoverage], <<-"end;", ["{}"], [])
+ Coverage.start
+ Coverage.suspend
+ p Coverage.result
+ end;
+ end
+
+ def test_resume_without_setup
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not set up yet/)
+ Coverage.resume
+ p :NG
+ end;
+ end
+
+ def test_suspend_without_setup
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not running/)
+ Coverage.suspend
+ p :NG
+ end;
+ end
+
+ def test_double_resume
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is already running/)
+ Coverage.start
+ Coverage.resume
+ p :NG
+ end;
+ end
+
+ def test_double_suspend
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not running/)
+ Coverage.setup
+ Coverage.suspend
+ p :NG
+ end;
+ end
end
diff --git a/test/csv/interface/test_read.rb b/test/csv/interface/test_read.rb
index b86c54fc9f6..d73622d554b 100644
--- a/test/csv/interface/test_read.rb
+++ b/test/csv/interface/test_read.rb
@@ -32,6 +32,24 @@ class TestCSVInterfaceRead < Test::Unit::TestCase
assert_equal(@rows, rows)
end
+ if respond_to?(:ractor)
+ ractor
+ def test_foreach_in_ractor
+ ractor = Ractor.new(@input.path) do |path|
+ rows = []
+ CSV.foreach(path, col_sep: "\t", row_sep: "\r\n").each do |row|
+ rows << row
+ end
+ rows
+ end
+ rows = [
+ ["1", "2", "3"],
+ ["4", "5"],
+ ]
+ assert_equal(rows, ractor.take)
+ end
+ end
+
def test_foreach_mode
rows = []
CSV.foreach(@input.path, "r", col_sep: "\t", row_sep: "\r\n").each do |row|
@@ -240,6 +258,20 @@ class TestCSVInterfaceRead < Test::Unit::TestCase
CSV.read(@input.path, col_sep: "\t", row_sep: "\r\n"))
end
+ if respond_to?(:ractor)
+ ractor
+ def test_read_in_ractor
+ ractor = Ractor.new(@input.path) do |path|
+ CSV.read(path, col_sep: "\t", row_sep: "\r\n")
+ end
+ rows = [
+ ["1", "2", "3"],
+ ["4", "5"],
+ ]
+ assert_equal(rows, ractor.take)
+ end
+ end
+
def test_readlines
assert_equal(@rows,
CSV.readlines(@input.path, col_sep: "\t", row_sep: "\r\n"))
diff --git a/test/csv/interface/test_read_write.rb b/test/csv/interface/test_read_write.rb
index 20c9fe317ec..c371e9c5fcf 100644
--- a/test/csv/interface/test_read_write.rb
+++ b/test/csv/interface/test_read_write.rb
@@ -112,4 +112,13 @@ a;b;c
assert_equal(CSV.instance,
CSV {|csv| csv})
end
+
+ def test_instance_shortcut_with_io
+ io = StringIO.new
+ from_instance = CSV.instance(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] }
+ from_shortcut = CSV(io, col_sep: ";") { |csv| csv << ["e", "f", "g"] }
+
+ assert_equal(from_instance, from_shortcut)
+ assert_equal(from_instance.string, "a;b;c\ne;f;g\n")
+ end
end
diff --git a/test/csv/interface/test_write.rb b/test/csv/interface/test_write.rb
index 8650ecd624a..02c2c5c5cee 100644
--- a/test/csv/interface/test_write.rb
+++ b/test/csv/interface/test_write.rb
@@ -25,6 +25,21 @@ class TestCSVInterfaceWrite < Test::Unit::TestCase
CSV
end
+ if respond_to?(:ractor)
+ ractor
+ def test_generate_default_in_ractor
+ ractor = Ractor.new do
+ CSV.generate do |csv|
+ csv << [1, 2, 3] << [4, nil, 5]
+ end
+ end
+ assert_equal(<<-CSV, ractor.take)
+1,2,3
+4,,5
+ CSV
+ end
+ end
+
def test_generate_append
csv_text = <<-CSV
1,2,3
@@ -101,6 +116,25 @@ a,b,c
CSV
end
+
+ if respond_to?(:ractor)
+ ractor
+ def test_append_row_in_ractor
+ ractor = Ractor.new(@output.path) do |path|
+ CSV.open(path, "wb") do |csv|
+ csv <<
+ CSV::Row.new([], ["1", "2", "3"]) <<
+ CSV::Row.new([], ["a", "b", "c"])
+ end
+ end
+ ractor.take
+ assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
+1,2,3
+a,b,c
+ CSV
+ end
+ end
+
def test_append_hash
CSV.open(@output.path, "wb", headers: true) do |csv|
csv << [:a, :b, :c]
diff --git a/test/csv/parse/test_invalid.rb b/test/csv/parse/test_invalid.rb
index 9dfd0813801..ddb59e2b9a0 100644
--- a/test/csv/parse/test_invalid.rb
+++ b/test/csv/parse/test_invalid.rb
@@ -36,4 +36,17 @@ ggg,hhh,iii
csv.shift)
assert_equal(true, csv.eof?)
end
+
+ def test_ignore_invalid_line_cr_lf
+ data = <<-CSV
+"1","OK"\r
+"2",""NOT" OK"\r
+"3","OK"\r
+CSV
+ csv = CSV.new(data)
+
+ assert_equal(['1', 'OK'], csv.shift)
+ assert_raise(CSV::MalformedCSVError) { csv.shift }
+ assert_equal(['3', 'OK'], csv.shift)
+ end
end
diff --git a/test/date/test_date_strftime.rb b/test/date/test_date_strftime.rb
index f82874d26d0..be9354504a5 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,
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 00000000000..2b0752a56a9
--- /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", error.to_s
+ end
+end
diff --git a/test/did_you_mean/test_spell_checker.rb b/test/did_you_mean/test_spell_checker.rb
index 98460b4d94f..8445380de33 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 d8f2f462736..00000000000
--- 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/did_you_mean/tree_spell/test_change_word.rb b/test/did_you_mean/tree_spell/test_change_word.rb
index 613e11b869b..7855b3de502 100644
--- a/test/did_you_mean/tree_spell/test_change_word.rb
+++ b/test/did_you_mean/tree_spell/test_change_word.rb
@@ -8,7 +8,7 @@ class ChangeWordTest < Test::Unit::TestCase
@len = @input.length
end
- def test_deleletion
+ def test_deletion
assert_match @cw.deletion(5), 'spec/ervices/anything_spec'
assert_match @cw.deletion(@len - 1), 'spec/services/anything_spe'
assert_match @cw.deletion(0), 'pec/services/anything_spec'
diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb
index acef380ad6b..f3d20201bc9 100644
--- a/test/drb/drbtest.rb
+++ b/test/drb/drbtest.rb
@@ -214,9 +214,9 @@ module DRbCore
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
+ omit if RUBY_PLATFORM.include?("armv7l-linux")
+ omit if RUBY_PLATFORM.include?("sparc-solaris2.10")
+ omit 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
diff --git a/test/error_highlight/test_error_highlight.rb b/test/error_highlight/test_error_highlight.rb
index 49bfee8f6c3..08036bca542 100644
--- a/test/error_highlight/test_error_highlight.rb
+++ b/test/error_highlight/test_error_highlight.rb
@@ -5,7 +5,7 @@ require "tempfile"
class ErrorHighlightTest < Test::Unit::TestCase
class DummyFormatter
- def message_for(corrections)
+ def self.message_for(corrections)
""
end
end
@@ -66,6 +66,18 @@ undefined method `foo' for nil:NilClass
end
end
+ def test_CALL_noarg_4
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `foo' for nil:NilClass
+
+ (nil).foo + 1
+ ^^^^
+ END
+
+ (nil).foo + 1
+ end
+ end
+
def test_CALL_arg_1
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for nil:NilClass
@@ -222,6 +234,18 @@ undefined method `[]' for #{ v.inspect }
end
end
+ def test_CALL_aref_5
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `[]' for nil:NilClass
+
+ (nil)[ ]
+ ^^^
+ END
+
+ (nil)[ ]
+ end
+ end
+
def test_CALL_aset
assert_error_message(NoMethodError, <<~END) do
undefined method `[]=' for nil:NilClass
@@ -313,6 +337,30 @@ undefined method `foo=' for nil:NilClass
end
end
+ def test_ATTRASGN_4
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `[]=' for nil:NilClass
+
+ (nil)[0] = 42
+ ^^^^^
+ END
+
+ (nil)[0] = 42
+ end
+ end
+
+ def test_ATTRASGN_5
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `foo=' for nil:NilClass
+
+ (nil).foo = 42
+ ^^^^^^
+ END
+
+ (nil).foo = 42
+ end
+ end
+
def test_OPCALL_binary_1
assert_error_message(NoMethodError, <<~END) do
undefined method `+' for nil:NilClass
@@ -338,7 +386,19 @@ undefined method `+' for nil:NilClass
end
end
- def test_OPCALL_unary
+ def test_OPCALL_binary_3
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `+' for nil:NilClass
+
+ (nil) + 42
+ ^
+ END
+
+ (nil) + 42
+ end
+ end
+
+ def test_OPCALL_unary_1
assert_error_message(NoMethodError, <<~END) do
undefined method `+@' for nil:NilClass
@@ -350,6 +410,18 @@ undefined method `+@' for nil:NilClass
end
end
+ def test_OPCALL_unary_2
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `+@' for nil:NilClass
+
+ +(nil)
+ ^
+ END
+
+ +(nil)
+ end
+ end
+
def test_FCALL_1
assert_error_message(NoMethodError, <<~END) do
undefined method `foo' for nil:NilClass
@@ -429,6 +501,20 @@ undefined method `[]' for nil:NilClass
end
end
+ def test_OP_ASGN1_aref_4
+ v = nil
+
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `[]' for nil:NilClass
+
+ (v)[0] += 42
+ ^^^
+ END
+
+ (v)[0] += 42
+ end
+ end
+
def test_OP_ASGN1_op_1
v = Object.new
def v.[](x); nil; end
@@ -475,6 +561,21 @@ undefined method `+' for nil:NilClass
end
end
+ def test_OP_ASGN1_op_4
+ v = Object.new
+ def v.[](x); nil; end
+
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `+' for nil:NilClass
+
+ (v)[0] += 42
+ ^
+ END
+
+ (v)[0] += 42
+ end
+ end
+
def test_OP_ASGN1_aset_1
v = Object.new
def v.[](x); 1; end
@@ -521,6 +622,21 @@ undefined method `[]=' for #{ v.inspect }
end
end
+ def test_OP_ASGN1_aset_4
+ v = Object.new
+ def v.[](x); 1; end
+
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `[]=' for #{ v.inspect }
+
+ (v)[0] += 42
+ ^^^^^^
+ END
+
+ (v)[0] += 42
+ end
+ end
+
def test_OP_ASGN2_read_1
v = nil
@@ -550,6 +666,20 @@ undefined method `foo' for nil:NilClass
end
end
+ def test_OP_ASGN2_read_3
+ v = nil
+
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `foo' for nil:NilClass
+
+ (v).foo += 42
+ ^^^^
+ END
+
+ (v).foo += 42
+ end
+ end
+
def test_OP_ASGN2_op_1
v = Object.new
def v.foo; nil; end
@@ -581,6 +711,21 @@ undefined method `+' for nil:NilClass
end
end
+ def test_OP_ASGN2_op_3
+ v = Object.new
+ def v.foo; nil; end
+
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `+' for nil:NilClass
+
+ (v).foo += 42
+ ^
+ END
+
+ (v).foo += 42
+ end
+ end
+
def test_OP_ASGN2_write_1
v = Object.new
def v.foo; 1; end
@@ -612,6 +757,21 @@ undefined method `foo=' for #{ v.inspect }
end
end
+ def test_OP_ASGN2_write_3
+ v = Object.new
+ def v.foo; 1; end
+
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `foo=' for #{ v.inspect }
+
+ (v).foo += 42
+ ^^^^^^^
+ END
+
+ (v).foo += 42
+ end
+ end
+
def test_CONST
assert_error_message(NameError, <<~END) do
uninitialized constant ErrorHighlightTest::NotDefined
diff --git a/test/excludes/TestArray.rb b/test/excludes/TestArray.rb
new file mode 100644
index 00000000000..73da272007c
--- /dev/null
+++ b/test/excludes/TestArray.rb
@@ -0,0 +1 @@
+exclude(:test_shared_marking, "The target code has already been changed")
diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb
index af64e4ebb6d..8c2fdcb0e06 100644
--- a/test/fiber/scheduler.rb
+++ b/test/fiber/scheduler.rb
@@ -60,6 +60,7 @@ class Scheduler
readable&.each do |io|
if fiber = @readable.delete(io)
+ @writable.delete(io) if @writable[io] == fiber
selected[fiber] = IO::READABLE
elsif io == @urgent.first
@urgent.first.read_nonblock(1024)
@@ -68,7 +69,8 @@ class Scheduler
writable&.each do |io|
if fiber = @writable.delete(io)
- selected[fiber] |= IO::WRITABLE
+ @readable.delete(io) if @readable[io] == fiber
+ selected[fiber] = selected.fetch(fiber, 0) | IO::WRITABLE
end
end
@@ -105,17 +107,31 @@ class Scheduler
end
end
- def close
+ def scheduler_close
+ close(true)
+ end
+
+ def close(internal = false)
# $stderr.puts [__method__, Fiber.current].inspect
- raise "Scheduler already closed!" if @closed
+ unless internal
+ if Fiber.scheduler == self
+ return Fiber.set_scheduler(nil)
+ end
+ end
+
+ if @closed
+ raise "Scheduler already closed!"
+ end
self.run
ensure
- @urgent.each(&:close)
- @urgent = nil
+ if @urgent
+ @urgent.each(&:close)
+ @urgent = nil
+ end
- @closed = true
+ @closed ||= true
# We freeze to detect any unintended modifications after the scheduler is closed:
self.freeze
@@ -240,3 +256,13 @@ class BrokenUnblockScheduler < Scheduler
raise "Broken unblock!"
end
end
+
+class SleepingUnblockScheduler < Scheduler
+ # This method is invoked when the thread is exiting.
+ def unblock(blocker, fiber)
+ super
+
+ # This changes the current thread state to `THREAD_RUNNING` which causes `thread_join_sleep` to hang.
+ sleep(0.1)
+ end
+end
diff --git a/test/fiber/test_io.rb b/test/fiber/test_io.rb
index fafda7c3102..ce65a55f780 100644
--- a/test/fiber/test_io.rb
+++ b/test/fiber/test_io.rb
@@ -97,4 +97,47 @@ class TestFiberIO < Test::Unit::TestCase
assert_kind_of Errno::EPIPE, error
end
+
+ def test_tcp_accept
+ server = TCPServer.new('localhost', 0)
+
+ th = Thread.new do
+ Fiber.set_scheduler(Scheduler.new)
+
+ Fiber.schedule do
+ sender = server.accept
+ sender.wait_writable
+ sender.write "hello"
+ sender.close
+ end
+ end
+
+ recver = TCPSocket.new('localhost', server.local_address.ip_port)
+ assert "hello", recver.read
+
+ recver.close
+ server.close
+ th.join
+ end
+
+ def test_tcp_connect
+ server = TCPServer.new('localhost', 0)
+
+ th = Thread.new do
+ Fiber.set_scheduler(Scheduler.new)
+
+ Fiber.schedule do
+ sender = TCPSocket.new('localhost', server.local_address.ip_port)
+ sender.write "hello"
+ sender.close
+ end
+ end
+
+ recver = server.accept
+ assert "hello", recver.read
+
+ recver.close
+ server.close
+ th.join
+ end
end
diff --git a/test/fiber/test_thread.rb b/test/fiber/test_thread.rb
index 843604b5f1c..5c25c43de29 100644
--- a/test/fiber/test_thread.rb
+++ b/test/fiber/test_thread.rb
@@ -20,6 +20,31 @@ class TestFiberThread < Test::Unit::TestCase
assert_equal :done, thread.value
end
+ def test_thread_join_implicit
+ sleeping = false
+ finished = false
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ sleeping = true
+ sleep(0.1)
+ finished = true
+ end
+
+ :done
+ end
+
+ Thread.pass until sleeping
+
+ thread.join
+
+ assert_equal :done, thread.value
+ assert finished, "Scheduler thread's task should be finished!"
+ end
+
def test_thread_join_blocking
thread = Thread.new do
scheduler = Scheduler.new
@@ -66,4 +91,18 @@ class TestFiberThread < Test::Unit::TestCase
thread.join
end
end
+
+ def test_thread_join_hang
+ thread = Thread.new do
+ scheduler = SleepingUnblockScheduler.new
+
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ Thread.new{sleep(0.01)}.value
+ end
+ end
+
+ thread.join
+ end
end
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb
index a6e20199249..0ea3bf57f47 100644
--- a/test/fiddle/helper.rb
+++ b/test/fiddle/helper.rb
@@ -1,4 +1,6 @@
# frozen_string_literal: true
+
+require 'rbconfig/sizeof'
require 'test/unit'
require 'fiddle'
@@ -56,6 +58,8 @@ when /mingw/, /mswin/
libc_so = libm_so = "#{crtname}.dll"
when /darwin/
libc_so = libm_so = "/usr/lib/libSystem.B.dylib"
+ # macOS 11.0+ removed libSystem.B.dylib from /usr/lib. But It works with dlopen.
+ rigid_path = true
when /kfreebsd/
libc_so = "/lib/libc.so.0.1"
libm_so = "/lib/libm.so.1"
@@ -131,12 +135,9 @@ else
end
end
-libc_so = nil if !libc_so || (libc_so[0] == ?/ && !File.file?(libc_so))
-libm_so = nil if !libm_so || (libm_so[0] == ?/ && !File.file?(libm_so))
-
-# macOS 11.0+ removed libSystem.B.dylib from /usr/lib. But It works with dlopen.
-if RUBY_PLATFORM =~ /darwin/
- libc_so = libm_so = "/usr/lib/libSystem.B.dylib"
+unless rigid_path
+ libc_so = nil if libc_so && libc_so[0] == ?/ && !File.file?(libc_so)
+ libm_so = nil if libm_so && libm_so[0] == ?/ && !File.file?(libm_so)
end
if !libc_so || !libm_so
@@ -166,5 +167,12 @@ module Fiddle
GC.start
end
end
+
+ def under_gc_stress
+ stress, GC.stress = GC.stress, true
+ yield
+ ensure
+ GC.stress = stress
+ end
end
end
diff --git a/test/fiddle/test_c_struct_builder.rb b/test/fiddle/test_c_struct_builder.rb
index 187424c92d7..ca44c6cf7a6 100644
--- a/test/fiddle/test_c_struct_builder.rb
+++ b/test/fiddle/test_c_struct_builder.rb
@@ -3,12 +3,45 @@ begin
require_relative 'helper'
require 'fiddle/struct'
require 'fiddle/cparser'
+ require 'fiddle/import'
rescue LoadError
end
module Fiddle
class TestCStructBuilder < TestCase
include Fiddle::CParser
+ extend Fiddle::Importer
+
+ RBasic = struct ['void * flags',
+ 'void * klass' ]
+
+
+ RObject = struct [
+ { 'basic' => RBasic },
+ { 'as' => union([
+ { 'heap'=> struct([ 'uint32_t numiv',
+ 'void * ivptr',
+ 'void * iv_index_tbl' ]) },
+ 'void *ary[3]' ])}
+ ]
+
+
+ def test_basic_embedded_members
+ assert_equal 0, RObject.offsetof("basic.flags")
+ assert_equal Fiddle::SIZEOF_VOIDP, RObject.offsetof("basic.klass")
+ end
+
+ def test_embedded_union_members
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as")
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap")
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.numiv")
+ assert_equal 3 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.ivptr")
+ assert_equal 4 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.iv_index_tbl")
+ end
+
+ def test_as_ary
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.ary")
+ end
def test_offsetof
types, members = parse_struct_signature(['int64_t i','char c'])
diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb
index 24e1800e591..ae319197a4d 100644
--- a/test/fiddle/test_cparser.rb
+++ b/test/fiddle/test_cparser.rb
@@ -326,7 +326,7 @@ module Fiddle
def test_signature_variadic_arguments
unless Fiddle.const_defined?("TYPE_VARIADIC")
- skip "libffi doesn't support variadic arguments"
+ omit "libffi doesn't support variadic arguments"
end
assert_equal([
"printf",
diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb
index d3604c79c35..44893017e8c 100644
--- a/test/fiddle/test_func.rb
+++ b/test/fiddle/test_func.rb
@@ -15,7 +15,7 @@ module Fiddle
begin
f = Function.new(@libm['sinf'], [TYPE_FLOAT], TYPE_FLOAT)
rescue Fiddle::DLError
- skip "libm may not have sinf()"
+ omit "libm may not have sinf()"
end
assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001
end
@@ -26,14 +26,13 @@ module Fiddle
end
def test_string
- stress, GC.stress = GC.stress, true
- f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
- buff = +"000"
- str = f.call(buff, "123")
- assert_equal("123", buff)
- assert_equal("123", str.to_s)
- ensure
- GC.stress = stress
+ under_gc_stress do
+ f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
+ buff = +"000"
+ str = f.call(buff, "123")
+ assert_equal("123", buff)
+ assert_equal("123", str.to_s)
+ end
end
def test_isdigit
@@ -76,13 +75,15 @@ module Fiddle
bug4929 = '[ruby-core:37395]'
buff = "9341"
- EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)}
+ under_gc_stress do
+ qsort.call(buff, buff.size, 1, cb)
+ end
assert_equal("1349", buff, bug4929)
end
def test_snprintf
unless Fiddle.const_defined?("TYPE_VARIADIC")
- skip "libffi doesn't support variadic arguments"
+ omit "libffi doesn't support variadic arguments"
end
if Fiddle::WINDOWS
snprintf_name = "_snprintf"
@@ -92,7 +93,7 @@ module Fiddle
begin
snprintf_pointer = @libc[snprintf_name]
rescue Fiddle::DLError
- skip "Can't find #{snprintf_name}: #{$!.message}"
+ omit "Can't find #{snprintf_name}: #{$!.message}"
end
snprintf = Function.new(snprintf_pointer,
[
diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb
index df632925ade..8ac4f60aa3a 100644
--- a/test/fiddle/test_function.rb
+++ b/test/fiddle/test_function.rb
@@ -164,7 +164,7 @@ module Fiddle
begin
poll = @libc['poll']
rescue Fiddle::DLError
- skip 'poll(2) not available'
+ omit 'poll(2) not available'
end
f = Function.new(poll, [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT)
@@ -180,9 +180,37 @@ module Fiddle
end
def test_no_memory_leak
- prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen_p"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"'
- code = 'begin r.call(a); rescue TypeError; end'
- assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2)
+ if respond_to?(:assert_nothing_leaked_memory)
+ rb_obj_frozen_p_symbol = Fiddle.dlopen(nil)["rb_obj_frozen_p"]
+ rb_obj_frozen_p = Fiddle::Function.new(rb_obj_frozen_p_symbol,
+ [Fiddle::TYPE_UINTPTR_T],
+ Fiddle::TYPE_UINTPTR_T)
+ a = "a"
+ n_tries = 100_000
+ n_tries.times do
+ begin
+ a + 1
+ rescue TypeError
+ end
+ end
+ n_arguments = 1
+ sizeof_fiddle_generic = Fiddle::SIZEOF_VOIDP # Rough
+ size_per_try =
+ (sizeof_fiddle_generic * n_arguments) +
+ (Fiddle::SIZEOF_VOIDP * (n_arguments + 1))
+ assert_nothing_leaked_memory(size_per_try * n_tries) do
+ n_tries.times do
+ begin
+ rb_obj_frozen_p.call(a)
+ rescue TypeError
+ end
+ end
+ end
+ else
+ prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen_p"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"'
+ code = 'begin r.call(a); rescue TypeError; end'
+ assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2)
+ end
end
private
diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb
index c0e85f70760..7e3ff9d8446 100644
--- a/test/fiddle/test_handle.rb
+++ b/test/fiddle/test_handle.rb
@@ -185,7 +185,16 @@ module Fiddle
end if /freebsd/=~ RUBY_PLATFORM
def test_no_memory_leak
- assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Handle.allocate}; GC.start', rss: true)
+ if respond_to?(:assert_nothing_leaked_memory)
+ n_tries = 100_000
+ assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do
+ n_tries.times do
+ Fiddle::Handle.allocate
+ end
+ end
+ else
+ assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Handle.allocate}; GC.start', rss: true)
+ end
end
if /cygwin|mingw|mswin/ =~ RUBY_PLATFORM
diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb
index 8130823fd65..240cda37df6 100644
--- a/test/fiddle/test_memory_view.rb
+++ b/test/fiddle/test_memory_view.rb
@@ -14,7 +14,7 @@ end
module Fiddle
class TestMemoryView < TestCase
def setup
- skip "MemoryView is unavailable" unless defined? Fiddle::MemoryView
+ omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView
end
def test_null_ptr
@@ -49,7 +49,7 @@ module Fiddle
end
def test_memory_view_multi_dimensional
- skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+ omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
buf = [ 1, 2, 3, 4,
5, 6, 7, 8,
@@ -71,7 +71,7 @@ module Fiddle
end
def test_memory_view_multi_dimensional_with_strides
- skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+ omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*")
@@ -93,7 +93,7 @@ module Fiddle
end
def test_memory_view_multi_dimensional_with_multiple_members
- skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+ omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
-1, -2, -3, -4, -5, -6, -7, -8].pack("s*")
diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb
index 88dad751387..7d708ee417e 100644
--- a/test/fiddle/test_pointer.rb
+++ b/test/fiddle/test_pointer.rb
@@ -179,16 +179,6 @@ module Fiddle
end
def test_free=
- assert_normal_exit(<<-"End", '[ruby-dev:39269]')
- require 'fiddle'
- include Fiddle
- free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
- ptr = Fiddle::Pointer.malloc(4)
- ptr.free = free
- free.ptr
- ptr.free.ptr
- End
-
free = Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
ptr = Pointer.malloc(4)
ptr.free = free
@@ -282,7 +272,16 @@ module Fiddle
end
def test_no_memory_leak
- assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true)
+ if respond_to?(:assert_nothing_leaked_memory)
+ n_tries = 100_000
+ assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do
+ n_tries.times do
+ Fiddle::Pointer.allocate
+ end
+ end
+ else
+ assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true)
+ end
end
end
end if defined?(Fiddle)
diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb
index 63936d1a050..36b5d6ef504 100644
--- a/test/fileutils/test_fileutils.rb
+++ b/test/fileutils/test_fileutils.rb
@@ -242,7 +242,7 @@ class TestFileUtils < Test::Unit::TestCase
#
def test_assert_output_lines
- assert_raise(MiniTest::Assertion) {
+ assert_raise(Test::Unit::AssertionFailedError) {
Timeout.timeout(0.5) {
assert_output_lines([]) {
Thread.current.report_on_exception = false
diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb
index 3d12b1f463c..d119ec23e03 100644
--- a/test/io/console/test_io_console.rb
+++ b/test/io/console/test_io_console.rb
@@ -375,7 +375,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)
diff --git a/test/irb/test_cmd.rb b/test/irb/test_cmd.rb
index e6bb587b5cb..8eee36badc6 100644
--- a/test/irb/test_cmd.rb
+++ b/test/irb/test_cmd.rb
@@ -509,6 +509,30 @@ module TestIRB
assert_match(%r[/irb\.rb], out)
end
+ def test_show_source_end_finder
+ pend if RUBY_ENGINE == 'truffleruby'
+ eval(code = <<-EOS, binding, __FILE__, __LINE__ + 1)
+ def show_source_test_method
+ unless true
+ end
+ end
+ EOS
+ input = TestInputMethod.new([
+ "show_source 'TestIRB::ExtendCommand#show_source_test_method'\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_include(out, code)
+ end
+
def test_whereami
input = TestInputMethod.new([
"whereami\n",
diff --git a/test/irb/test_color.rb b/test/irb/test_color.rb
index ba99b1253f4..6ad64a0ae24 100644
--- a/test/irb/test_color.rb
+++ b/test/irb/test_color.rb
@@ -147,7 +147,7 @@ module TestIRB
def test_colorize_code_complete_true
unless complete_option_supported?
- skip '`complete: true` is the same as `complete: false` in Ruby 2.6-'
+ pend '`complete: true` is the same as `complete: false` in Ruby 2.6-'
end
# `complete: true` behaviors. Warn end-of-file.
diff --git a/test/irb/test_color_printer.rb b/test/irb/test_color_printer.rb
index 1afc7ccf551..93ec7001465 100644
--- a/test/irb/test_color_printer.rb
+++ b/test/irb/test_color_printer.rb
@@ -30,7 +30,7 @@ module TestIRB
def test_color_printer
unless ripper_lexer_scan_supported?
- skip 'Ripper::Lexer#scan is supported in Ruby 2.7+'
+ pend 'Ripper::Lexer#scan is supported in Ruby 2.7+'
end
{
1 => "#{BLUE}#{BOLD}1#{CLEAR}\n",
diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb
index 535690ae226..3aa99d74d34 100644
--- a/test/irb/test_completion.rb
+++ b/test/irb/test_completion.rb
@@ -17,7 +17,7 @@ module TestIRB
status = assert_in_out_err(cmds, "", //, [], bug5938)
assert(status.success?, bug5938)
rescue LoadError
- skip "cannot load irb/completion"
+ pend "cannot load irb/completion"
end
end
@@ -27,11 +27,27 @@ module TestIRB
end
def test_complete_symbol
+ %w"UTF-16LE UTF-7".each 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))
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))
+ end
+
+ def test_complete_absolute_constants_with_special_characters
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A:", bind: binding))
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A.", bind: binding))
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A(", bind: binding))
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A)", bind: binding))
+ end
+
def test_complete_symbol_failure
assert_nil(IRB::InputCompletor::PerfectMatchedProc.(":aiueo", bind: binding))
end
@@ -68,6 +84,12 @@ module TestIRB
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
+ end
+
def test_complete_require_relative
candidates = Dir.chdir(__dir__ + "/../..") do
IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
@@ -83,5 +105,18 @@ module TestIRB
assert_include candidates, word
end
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")
+ 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")
+ end
end
end
diff --git a/test/irb/test_context.rb b/test/irb/test_context.rb
index 71e8ad1c0d1..d908195e6a5 100644
--- a/test/irb/test_context.rb
+++ b/test/irb/test_context.rb
@@ -79,7 +79,7 @@ module TestIRB
end
def test_evaluate_with_encoding_error_without_lineno
- skip if RUBY_ENGINE == 'truffleruby'
+ 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.
@@ -87,14 +87,14 @@ module TestIRB
end
def test_evaluate_with_onigmo_warning
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
assert_warning("(irb):1: warning: character class has duplicated range: /[aa]/\n") do
@context.evaluate('/[aa]/', 1)
end
end
def test_eval_input
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
"raise 'Foo'\n",
@@ -117,7 +117,7 @@ module TestIRB
end
def test_eval_input_raise2x
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
input = TestInputMethod.new([
"raise 'Foo'\n",
"raise 'Bar'\n",
@@ -159,6 +159,7 @@ module TestIRB
def test_default_config
assert_equal(true, @context.use_colorize?)
+ assert_equal(true, @context.use_autocomplete?)
end
def test_assignment_expression
@@ -220,7 +221,7 @@ module TestIRB
# The default
irb.context.echo = true
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -230,7 +231,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -240,7 +241,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -250,7 +251,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -268,7 +269,7 @@ module TestIRB
irb.context.echo = true
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -277,7 +278,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -286,7 +287,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -295,7 +296,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -304,7 +305,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -313,7 +314,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -332,7 +333,7 @@ module TestIRB
irb.context.echo = true
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -342,7 +343,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -352,7 +353,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -362,7 +363,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -372,7 +373,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -382,7 +383,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -429,7 +430,7 @@ module TestIRB
# The default
irb.context.newline_before_multiline_output = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -439,7 +440,7 @@ module TestIRB
# No newline before multiline output
input.reset
irb.context.newline_before_multiline_output = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -447,8 +448,30 @@ module TestIRB
out)
end
+ def test_default_return_format
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_N => "%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("3\n",
+ out)
+ end
+
def test_eval_input_with_exception
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
"def hoge() fuga; end; def fuga() raise; end; hoge\n",
@@ -470,6 +493,7 @@ module TestIRB
:*, /\(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)
@@ -478,7 +502,7 @@ module TestIRB
end
def test_eval_input_with_invalid_byte_sequence_exception
- skip if RUBY_ENGINE == 'truffleruby'
+ 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},
@@ -500,6 +524,7 @@ module TestIRB
:*, /\(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)
@@ -508,7 +533,7 @@ module TestIRB
end
def test_eval_input_with_long_exception
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
nesting = 20
generated_code = ''
@@ -527,7 +552,7 @@ module TestIRB
if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
expected = [
:*, /Traceback \(most recent call last\):\n/,
- :*, /\t... 5 levels...\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/,
@@ -565,7 +590,7 @@ module TestIRB
:*, /\tfrom \(irb\):1:in `a6'\n/,
:*, /\tfrom \(irb\):1:in `a5'\n/,
:*, /\tfrom \(irb\):1:in `a4'\n/,
- :*, /\t... 5 levels...\n/,
+ :*, /\t... \d+ levels...\n/,
]
end
assert_pattern_list(expected, out)
diff --git a/test/irb/test_raise_no_backtrace_exception.rb b/test/irb/test_raise_no_backtrace_exception.rb
index 3031f000ed3..530adc0cbf1 100644
--- a/test/irb/test_raise_no_backtrace_exception.rb
+++ b/test/irb/test_raise_no_backtrace_exception.rb
@@ -4,7 +4,7 @@ require 'test/unit'
module TestIRB
class TestRaiseNoBacktraceException < Test::Unit::TestCase
def test_raise_exception
- skip if RUBY_ENGINE == 'truffleruby'
+ 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")
@@ -15,7 +15,7 @@ IRB
end
def test_raise_exception_with_invalid_byte_sequence
- skip if RUBY_ENGINE == 'truffleruby' || /mswin|mingw/ =~ RUBY_PLATFORM
+ 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"
@@ -23,7 +23,7 @@ IRB
end
def test_raise_exception_with_different_encoding_containing_invalid_byte_sequence
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
backup_home = ENV["HOME"]
Dir.mktmpdir("test_irb_raise_no_backtrace_exception_#{$$}") do |tmpdir|
ENV["HOME"] = tmpdir
diff --git a/test/irb/test_ruby_lex.rb b/test/irb/test_ruby_lex.rb
index 556afbd7760..e02370d3f74 100644
--- a/test/irb/test_ruby_lex.rb
+++ b/test/irb/test_ruby_lex.rb
@@ -109,8 +109,8 @@ module TestIRB
Row.new(%q( ]), 4, 4),
Row.new(%q( ]), 2, 2),
Row.new(%q(]), 0, 0),
- Row.new(%q([<<FOO]), nil, 0),
- Row.new(%q(hello), nil, 0),
+ Row.new(%q([<<FOO]), 0, 0),
+ Row.new(%q(hello), 0, 0),
Row.new(%q(FOO), nil, 0),
]
@@ -136,9 +136,29 @@ module TestIRB
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')
- skip 'Endless range is available in 2.6.0 or later'
+ pend 'Endless range is available in 2.6.0 or later'
end
input_with_prompt = [
PromptRow.new('001:0: :> ', %q(a = 3..)),
@@ -445,10 +465,10 @@ module TestIRB
def test_heredoc_with_indent
input_with_correct_indents = [
- Row.new(%q(<<~Q), nil, 0, 0),
- Row.new(%q({), nil, 0, 0),
- Row.new(%q( #), nil, 0, 0),
- Row.new(%q(}), nil, 0, 0),
+ 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)
]
lines = []
@@ -479,12 +499,12 @@ module TestIRB
def test_broken_heredoc
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
- skip 'This test needs Ripper::Lexer#scan to take broken tokens'
+ 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), nil, 2, 1),
- Row.new(%q( Qend), nil, 2, 1),
+ Row.new(%q( <<~Q), 2, 2, 1),
+ Row.new(%q( Qend), 2, 2, 1),
]
lines = []
@@ -511,7 +531,7 @@ module TestIRB
end
def assert_dynamic_prompt(lines, expected_prompt_list)
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
ruby_lex = RubyLex.new()
io = MockIO_DynamicPrompt.new(lines) do |prompt_list|
error_message = <<~EOM
@@ -555,7 +575,7 @@ module TestIRB
def test_broken_percent_literal
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
- skip 'This test needs Ripper::Lexer#scan to take broken tokens'
+ pend 'This test needs Ripper::Lexer#scan to take broken tokens'
end
tokens = RubyLex.ripper_lex_without_warning('%wwww')
@@ -568,7 +588,7 @@ module TestIRB
def test_broken_percent_literal_in_method
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
- skip 'This test needs Ripper::Lexer#scan to take broken tokens'
+ pend 'This test needs Ripper::Lexer#scan to take broken tokens'
end
tokens = RubyLex.ripper_lex_without_warning(<<~EOC.chomp)
diff --git a/test/irb/test_workspace.rb b/test/irb/test_workspace.rb
index f028fc3aa2c..1a1dc1f49b5 100644
--- a/test/irb/test_workspace.rb
+++ b/test/irb/test_workspace.rb
@@ -39,8 +39,8 @@ module TestIRB
end
def test_code_around_binding_with_existing_unreadable_file
- skip 'chmod cannot make file unreadable on windows' if windows?
- skip 'skipped in root privilege' if Process.uid == 0
+ pend 'chmod cannot make file unreadable on windows' if windows?
+ pend 'skipped in root privilege' if Process.uid == 0
Tempfile.create('irb') do |f|
code = "IRB::WorkSpace.new(binding)\n"
@@ -80,6 +80,23 @@ 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__}/../.."
+ irb_path = nil
+ %w[exe libexec].find do |dir|
+ 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)
+ version = 'xyz' # typical rubygems loading file
+ load('#{irb_path}')
+ RUBY
+ end
+
private
def with_script_lines
diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb
index 8f55b38a939..7ed98b11c1a 100644
--- a/test/irb/yamatanooroti/test_rendering.rb
+++ b/test/irb/yamatanooroti/test_rendering.rb
@@ -29,7 +29,7 @@ begin
write_irbrc <<~'LINES'
puts 'start IRB'
LINES
- start_terminal(25, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
write(<<~EOC)
'Hello, World!'
EOC
@@ -46,7 +46,7 @@ begin
write_irbrc <<~'LINES'
puts 'start IRB'
LINES
- start_terminal(25, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
write(<<~EOC)
class A
def inspect; '#<A>'; end
@@ -85,7 +85,7 @@ begin
write_irbrc <<~'LINES'
puts 'start IRB'
LINES
- start_terminal(40, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
write(<<~EOC)
class A
def inspect; '#<A>'; end
@@ -153,6 +153,69 @@ begin
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:0> :`
+ => :`
+ irb(main):002:0>
+ EOC
+ end
+
+ def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_right
+ pend "Needs a dummy document to show doc"
+ write_irbrc <<~'LINES'
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_N => "%03n> ",
+ :PROMPT_S => "%03n> ",
+ :PROMPT_C => "%03n> "
+ }
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+ puts 'start IRB'
+ LINES
+ start_terminal(4, 19, %W{ruby -I/home/aycabta/ruby/reline/lib -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("Str\C-i")
+ close
+ assert_screen(<<~EOC)
+ 001> String
+ StringPress A
+ StructString
+ of byte
+ EOC
+ end
+
+ def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_left
+ pend "Needs a dummy document to show doc"
+ write_irbrc <<~'LINES'
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_N => "%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("Str\C-i")
+ close
+ assert_screen(<<~EOC)
+ 001> String
+ PressString
+ StrinStruct
+ of by
+ EOC
+ end
+
private def write_irbrc(content)
File.open(@irbrc_file, 'w') do |f|
f.write content
diff --git a/test/lib/jit_support.rb b/test/lib/jit_support.rb
index 3bca63a549a..779aa8567e2 100644
--- a/test/lib/jit_support.rb
+++ b/test/lib/jit_support.rb
@@ -39,6 +39,7 @@ module JITSupport
'--disable-gems', "--jit-verbose=#{verbose}",
"--jit-min-calls=#{min_calls}", "--jit-max-cache=#{max_cache}",
]
+ args << '--disable-yjit'
args << '--jit-wait' if wait
args << '--jit-save-temps' if save_temps
args << '--jit-debug' if defined?(@jit_debug) && @jit_debug
diff --git a/test/logger/helper.rb b/test/logger/helper.rb
deleted file mode 100644
index 9eaeb205b0c..00000000000
--- a/test/logger/helper.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-ROOT_DIR = File.dirname(__dir__)
-$LOAD_PATH.unshift File.join(ROOT_DIR, 'lib') # to use logger in this repo instead of ruby built-in logger
-$LOAD_PATH.unshift File.join(ROOT_DIR, 'test', 'lib') # to use custom test-unit in this repo
-require 'logger'
-require 'test/unit'
-
-begin
- # for standalone test suite on ruby/logger
- require 'core_assertions'
-
- Test::Unit::TestCase.include Test::Unit::CoreAssertions
-rescue LoadError
-end
diff --git a/test/logger/test_logdevice.rb b/test/logger/test_logdevice.rb
index 6fefd356cd2..d360fa2107d 100644
--- a/test/logger/test_logdevice.rb
+++ b/test/logger/test_logdevice.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
require 'tempfile'
require 'tmpdir'
diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb
index 4bbfd523c05..3281d17c7bb 100644
--- a/test/logger/test_logger.rb
+++ b/test/logger/test_logger.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
require 'tempfile'
class TestLogger < Test::Unit::TestCase
diff --git a/test/logger/test_logperiod.rb b/test/logger/test_logperiod.rb
index 3c5cbbcd9b7..6e6e5e95337 100644
--- a/test/logger/test_logperiod.rb
+++ b/test/logger/test_logperiod.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
require 'time'
class TestLogPeriod < Test::Unit::TestCase
diff --git a/test/logger/test_severity.rb b/test/logger/test_severity.rb
index 1197e8abb9a..dad63472a6f 100644
--- a/test/logger/test_severity.rb
+++ b/test/logger/test_severity.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
class TestLoggerSeverity < Test::Unit::TestCase
def test_enum
diff --git a/test/mkmf/test_have_var.rb b/test/mkmf/test_have_var.rb
deleted file mode 100644
index 5367ec22484..00000000000
--- 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/net/http/test_httpresponse.rb b/test/net/http/test_httpresponse.rb
index cb86b546480..00b0072e706 100644
--- a/test/net/http/test_httpresponse.rb
+++ b/test/net/http/test_httpresponse.rb
@@ -79,7 +79,7 @@ EOS
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?
- skip 'too unstable with --jit-wait, and extending read_timeout did not help it'
+ omit 'too unstable with --jit-wait, and extending read_timeout did not help it'
end
IO.pipe do |r, w|
buf = 'x' * 1024
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 8ed04f59c9b..a1954d56a97 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)})
+ 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
diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb
index c36d6b89d8b..3f0622f94fd 100644
--- a/test/openssl/test_bn.rb
+++ b/test/openssl/test_bn.rb
@@ -248,6 +248,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
diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb
index 769e65ceb5a..24a215a4867 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,12 +84,12 @@ __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
OpenSSL::Config.parse("foo = $bar")
diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb
index 8d7046e8311..84c128c12ff 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)
diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb
index 8316ec2a9cb..4249b4afb70 100644
--- a/test/openssl/test_pair.rb
+++ b/test/openssl/test_pair.rb
@@ -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
@@ -383,7 +382,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 +429,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 fdbe753b17e..ec676743bcb 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,7 +156,8 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
nil,
nil,
2048
@@ -165,148 +170,144 @@ 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")
-
- 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)
- end
-
def test_new_with_no_keys
# generated with:
- # openssl pkcs12 -in <@mycert> -nokeys -export -out <out>
+ # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <@mycert> -nokeys -export
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=
+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>
+ # openssl pkcs12 -inkey fixtures/openssl/pkey/rsa-1.pem -nocerts -export
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==
+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_pkey.rb b/test/openssl/test_pkey.rb
index 4a539d8c469..544340e3788 100644
--- a/test/openssl/test_pkey.rb
+++ b/test/openssl/test_pkey.rb
@@ -27,20 +27,16 @@ 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")
}
# Parameter generation callback is called
@@ -59,14 +55,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
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index f80af8f8415..757704caf67 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -40,12 +40,14 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
def test_DHparams
dh1024 = Fixtures.pkey("dh1024")
+ dh1024params = dh1024.public_key
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(dh1024.p),
OpenSSL::ASN1::Integer(dh1024.g)
])
key = OpenSSL::PKey::DH.new(asn1.to_der)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh1024params, key
pem = <<~EOF
-----BEGIN DH PARAMETERS-----
@@ -55,9 +57,9 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
-----END DH PARAMETERS-----
EOF
key = OpenSSL::PKey::DH.new(pem)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh1024params, key
key = OpenSSL::PKey.read(pem)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh1024params, key
assert_equal asn1.to_der, dh1024.to_der
assert_equal pem, dh1024.export
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index 147e50176b2..0994607f21a 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -138,6 +138,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 +155,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 +168,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, key.to_der
+ assert_equal pem, key.export
- assert_equal asn1.to_der, dup_public(dsa512).to_der
- assert_equal pem, dup_public(dsa512).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
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 0a460bd5361..3f5958af50b 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -1,7 +1,7 @@
# 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
@@ -210,6 +210,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 +223,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 +232,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
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index 5e127f54075..dbe87ba4c1b 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -11,7 +11,7 @@ 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
@@ -201,7 +201,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
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"
@@ -216,7 +216,7 @@ 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"
@@ -346,13 +346,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 +364,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 +385,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,10 +396,15 @@ 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
@@ -482,12 +491,6 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
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
- end
-
def test_dup
key = Fixtures.pkey("rsa1024")
key2 = key.dup
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 5dccac5facc..65dbe7ac241 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -4,6 +4,17 @@ require_relative "utils"
if defined?(OpenSSL)
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
@@ -124,9 +135,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],
@@ -526,6 +534,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 +562,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 +604,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|
@@ -832,7 +839,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
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 +890,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
@@ -1028,7 +1033,9 @@ 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)
}
}
@@ -1331,7 +1338,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,7 +1360,6 @@ 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)
@@ -1375,7 +1380,6 @@ 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)
@@ -1400,7 +1404,6 @@ 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)
@@ -1414,7 +1417,6 @@ 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)
@@ -1428,7 +1430,6 @@ 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)
@@ -1469,56 +1470,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 +1579,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
@@ -1605,10 +1599,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_connect_works_when_setting_dh_callback_to_nil
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
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 +1613,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 +1663,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 {
diff --git a/test/openssl/test_ssl_session.rb b/test/openssl/test_ssl_session.rb
index a98efdae2a5..b72b10d3b5f 100644
--- a/test/openssl/test_ssl_session.rb
+++ b/test/openssl/test_ssl_session.rb
@@ -5,8 +5,6 @@ if defined?(OpenSSL)
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|
@@ -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 8e31a7d28d2..7cb1a1fe8eb 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)
@@ -338,6 +344,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 +602,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/utils.rb b/test/openssl/utils.rb
index 8ee0116412e..4ebcb9837bc 100644
--- a/test/openssl/utils.rb
+++ b/test/openssl/utils.rb
@@ -189,13 +189,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 +215,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 +228,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 +244,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 +261,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)
@@ -294,8 +280,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
timeout = EnvUtil.apply_timeout_scale(30)
th.join(timeout) or
th.raise(RuntimeError, "[start_server] thread did not exit in #{timeout} secs")
- rescue (defined?(MiniTest::Skip) ? MiniTest::Skip : Test::Unit::PendedError)
- # MiniTest::Skip is for the Ruby tree
+ rescue Test::Unit::PendedError
pend = $!
rescue Exception
end
@@ -313,32 +298,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_did_you_mean.rb b/test/optparse/test_did_you_mean.rb
index 763062586cc..39129ffb19b 100644
--- a/test/optparse/test_did_you_mean.rb
+++ b/test/optparse/test_did_you_mean.rb
@@ -36,14 +36,6 @@ 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
assert_raise_with_message(OptionParser::AmbiguousOption, /ambiguous option: --ba\nDid you mean\?\s+bar\s+baz\Z/) do
@opt.permute!(%w"--ba")
diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb
index 1fd7d878114..4ec4d43084e 100644
--- a/test/ostruct/test_ostruct.rb
+++ b/test/ostruct/test_ostruct.rb
@@ -368,6 +368,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])
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 8a0f3cbb665..9e14668c99f 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -815,7 +815,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_birthtime
- skip if RUBY_PLATFORM =~ /android/
+ omit if RUBY_PLATFORM =~ /android/
# Check under a (probably) local filesystem.
# Remote filesystems often may not support birthtime.
with_tmpchdir('rubytest-pathname') do |dir|
@@ -823,9 +823,9 @@ class TestPathname < Test::Unit::TestCase
assert_kind_of(Time, Pathname("a").birthtime)
rescue Errno::EPERM
# Docker prohibits statx syscall by the default.
- skip("statx(2) is prohibited by seccomp")
+ omit("statx(2) is prohibited by seccomp")
rescue Errno::ENOSYS
- skip("statx(2) is not supported on this filesystem")
+ omit("statx(2) is not supported on this filesystem")
rescue NotImplementedError
# assert_raise(NotImplementedError) do
# File.birthtime("a")
@@ -1120,7 +1120,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_grpowned?
- skip "Unix file owner test" if DOSISH
+ omit "Unix file owner test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
File.chown(-1, Process.gid, "f")
@@ -1175,7 +1175,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_world_readable?
- skip "Unix file mode bit test" if DOSISH
+ omit "Unix file mode bit test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
File.chmod(0400, "f")
@@ -1227,7 +1227,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_sticky?
- skip "Unix file mode bit test" if DOSISH
+ omit "Unix file mode bit test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
assert_equal(false, Pathname("f").sticky?)
@@ -1249,7 +1249,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_world_writable?
- skip "Unix file mode bit test" if DOSISH
+ omit "Unix file mode bit test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
File.chmod(0600, "f")
@@ -1409,8 +1409,8 @@ class TestPathname < Test::Unit::TestCase
a = []; Pathname("d").find(ignore_error: true) {|v| a << v }; a.sort!
assert_equal([Pathname("d"), Pathname("d/x")], a)
- skip "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
- skip 'skipped in root privilege' if Process.uid == 0
+ omit "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit 'skipped in root privilege' if Process.uid == 0
a = [];
assert_raise_with_message(Errno::EACCES, %r{d/x}) do
Pathname(".").find(ignore_error: false) {|v| a << v }
@@ -1429,10 +1429,22 @@ class TestPathname < Test::Unit::TestCase
}
end
+ def assert_mode(val, mask, path, mesg = nil)
+ st = File.stat(path)
+ assert_equal(val.to_s(8), (st.mode & mask).to_s(8), st.inspect)
+ end
+
def test_mkpath
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
assert_file.directory?("a/b/c/d")
+ unless File.stat(dir).world_readable?
+ # mktmpdir should make unreadable
+ Pathname("x/y/z").mkpath(mode: 0775)
+ assert_mode(0775, 0777, "x")
+ assert_mode(0775, 0777, "x/y")
+ assert_mode(0775, 0777, "x/y/z")
+ end
}
end
diff --git a/test/pathname/test_ractor.rb b/test/pathname/test_ractor.rb
index 9ce43ef640b..3d7b63deed4 100644
--- a/test/pathname/test_ractor.rb
+++ b/test/pathname/test_ractor.rb
@@ -4,7 +4,7 @@ require "pathname"
class TestPathnameRactor < Test::Unit::TestCase
def setup
- skip unless defined? Ractor
+ omit unless defined? Ractor
end
def test_ractor_shareable
diff --git a/test/psych/test_scalar_scanner.rb b/test/psych/test_scalar_scanner.rb
index 1bd6488e754..ebc9fbdcd2e 100644
--- a/test/psych/test_scalar_scanner.rb
+++ b/test/psych/test_scalar_scanner.rb
@@ -66,6 +66,10 @@ module Psych
assert_equal(1 / 0.0, ss.tokenize('.inf'))
end
+ def test_scan_plus_inf
+ assert_equal(1 / 0.0, ss.tokenize('+.inf'))
+ end
+
def test_scan_minus_inf
assert_equal(-1 / 0.0, ss.tokenize('-.inf'))
end
@@ -111,7 +115,15 @@ module Psych
end
def test_scan_strings_starting_with_underscores
- assert_equal "_100", ss.tokenize('_100')
+ assert_equal '_100', ss.tokenize('_100')
+ end
+
+ def test_scan_strings_starting_with_number
+ assert_equal '450D', ss.tokenize('450D')
+ end
+
+ def test_scan_strings_ending_with_underscores
+ assert_equal '100_', ss.tokenize('100_')
end
def test_scan_int_commas_and_underscores
@@ -120,7 +132,10 @@ module Psych
assert_equal 123_456_789, ss.tokenize('123_456_789')
assert_equal 123_456_789, ss.tokenize('123,456,789')
assert_equal 123_456_789, ss.tokenize('1_2,3,4_5,6_789')
- assert_equal 123_456_789, ss.tokenize('1_2,3,4_5,6_789_')
+
+ assert_equal 1, ss.tokenize('1')
+ assert_equal 1, ss.tokenize('+1')
+ assert_equal(-1, ss.tokenize('-1'))
assert_equal 0b010101010, ss.tokenize('0b010101010')
assert_equal 0b010101010, ss.tokenize('0b0,1_0,1_,0,1_01,0')
@@ -133,5 +148,35 @@ module Psych
assert_equal 0x123456789abcdef, ss.tokenize('0x_12_,34,_56,_789abcdef')
assert_equal 0x123456789abcdef, ss.tokenize('0x12_,34,_56,_789abcdef__')
end
+
+ def test_scan_dot
+ assert_equal '.', ss.tokenize('.')
+ end
+
+ def test_scan_plus_dot
+ assert_equal '+.', ss.tokenize('+.')
+ end
+
+ class MatchCallCounter < String
+ attr_reader :match_call_count
+
+ def match?(pat)
+ @match_call_count ||= 0
+ @match_call_count += 1
+ super
+ end
+ end
+
+ def test_scan_ascii_matches_quickly
+ ascii = MatchCallCounter.new('abcdefghijklmnopqrstuvwxyz')
+ ss.tokenize(ascii)
+ assert_equal 1, ascii.match_call_count
+ end
+
+ def test_scan_unicode_matches_quickly
+ unicode = MatchCallCounter.new('鳥かご関連用品')
+ ss.tokenize(unicode)
+ assert_equal 1, unicode.match_call_count
+ end
end
end
diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb
index 20ab79c05a1..0dc34b3083d 100644
--- a/test/psych/test_string.rb
+++ b/test/psych/test_string.rb
@@ -17,6 +17,19 @@ module Psych
end
end
+ # 'y' and 'n' are kind of ambiguous. Syck treated y and n 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"))
+ end
+
def test_string_with_newline
assert_equal "1\n2", Psych.load("--- ! '1\n\n 2'\n")
end
diff --git a/test/racc/assets/mof.y b/test/racc/assets/mof.y
index da3172988f7..2e83c79b6f2 100644
--- a/test/racc/assets/mof.y
+++ b/test/racc/assets/mof.y
@@ -563,9 +563,9 @@ end # class Parser
require 'strscan'
require 'rubygems'
require 'cim'
-require File.join(File.dirname(__FILE__), 'result')
-require File.join(File.dirname(__FILE__), 'scanner')
-require File.join(File.dirname(__FILE__), 'helper')
+require File.join(__dir__, 'result')
+require File.join(__dir__, 'scanner')
+require File.join(__dir__, 'case')
---- inner ----
diff --git a/test/racc/helper.rb b/test/racc/case.rb
index 146beb5a737..f4240bfd219 100644
--- a/test/racc/helper.rb
+++ b/test/racc/case.rb
@@ -3,11 +3,6 @@ $VERBOSE = true
begin
require 'test/unit'
-begin
- require_relative './lib/core_assertions'
- Test::Unit::TestCase.include Test::Unit::CoreAssertions
-rescue LoadError
-end
require 'racc/static'
require 'fileutils'
require 'tempfile'
@@ -15,7 +10,7 @@ require 'timeout'
module Racc
class TestCase < Test::Unit::TestCase
- PROJECT_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ 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)
diff --git a/test/racc/regress/mof b/test/racc/regress/mof
index 836604744b1..d702292e516 100644
--- a/test/racc/regress/mof
+++ b/test/racc/regress/mof
@@ -12,9 +12,9 @@ require 'racc/parser.rb'
require 'strscan'
require 'rubygems'
require 'cim'
-require File.join(File.dirname(__FILE__), 'result')
-require File.join(File.dirname(__FILE__), 'scanner')
-require File.join(File.dirname(__FILE__), 'helper')
+require File.join(__dir__, 'result')
+require File.join(__dir__, 'scanner')
+require File.join(__dir__, 'case')
module MOF
class Parser < Racc::Parser
diff --git a/test/racc/test_chk_y.rb b/test/racc/test_chk_y.rb
index bb8b6b4fe3d..883737c45f6 100644
--- a/test/racc/test_chk_y.rb
+++ b/test/racc/test_chk_y.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestChkY < TestCase
diff --git a/test/racc/test_grammar_file_parser.rb b/test/racc/test_grammar_file_parser.rb
index b187bdcaec9..8f6e090cb28 100644
--- a/test/racc/test_grammar_file_parser.rb
+++ b/test/racc/test_grammar_file_parser.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestGrammarFileParser < TestCase
diff --git a/test/racc/test_racc_command.rb b/test/racc/test_racc_command.rb
index 0d2c5829e4a..5bfebf150be 100644
--- a/test/racc/test_racc_command.rb
+++ b/test/racc/test_racc_command.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestRaccCommand < TestCase
diff --git a/test/racc/test_scan_y.rb b/test/racc/test_scan_y.rb
index 4c60119119d..fcd7e53c996 100644
--- a/test/racc/test_scan_y.rb
+++ b/test/racc/test_scan_y.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestScanY < TestCase
diff --git a/test/rdoc/support/test_case.rb b/test/rdoc/support/test_case.rb
index 6d397625e8f..7617fc84718 100644
--- a/test/rdoc/support/test_case.rb
+++ b/test/rdoc/support/test_case.rb
@@ -1,16 +1,3 @@
-##
-# RDoc::TestCase is an abstract TestCase to provide common setup and teardown
-# across all RDoc tests. The test case uses minitest, so all the assertions
-# of minitest may be used.
-#
-# The testcase provides the following:
-#
-# * A reset code-object tree
-# * A reset markup preprocessor (RDoc::Markup::PreProcess)
-# * The <code>@RM</code> alias of RDoc::Markup (for less typing)
-# * <code>@pwd</code> containing the current working directory
-# * FileUtils, pp, Tempfile, Dir.tmpdir and StringIO
-
require 'bundler/errors'
begin
gem 'test-unit'
@@ -30,8 +17,8 @@ require 'rdoc'
##
# RDoc::TestCase is an abstract TestCase to provide common setup and teardown
-# across all RDoc tests. The test case uses minitest, so all the assertions
-# of minitest may be used.
+# across all RDoc tests. The test case uses test-unit, so all the assertions
+# of test-unit may be used.
#
# The testcase provides the following:
#
diff --git a/test/rdoc/test_rdoc_any_method.rb b/test/rdoc/test_rdoc_any_method.rb
index 615789dfb35..caff86b0595 100644
--- a/test/rdoc/test_rdoc_any_method.rb
+++ b/test/rdoc/test_rdoc_any_method.rb
@@ -72,6 +72,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' },
diff --git a/test/rdoc/test_rdoc_cross_reference.rb b/test/rdoc/test_rdoc_cross_reference.rb
index 183de0930d3..94ddc1e1e47 100644
--- a/test/rdoc/test_rdoc_cross_reference.rb
+++ b/test/rdoc/test_rdoc_cross_reference.rb
@@ -20,7 +20,7 @@ class TestRDocCrossReference < XrefTestCase
def test_METHOD_REGEXP_STR
re = /#{RDoc::CrossReference::METHOD_REGEXP_STR}/
- %w'=== [] []= << >>'.each do |x|
+ %w'== === [] []= << >>'.each do |x|
re =~ x
assert_equal x, $&
end
diff --git a/test/rdoc/test_rdoc_generator_darkfish.rb b/test/rdoc/test_rdoc_generator_darkfish.rb
index f5858bce6e6..b78a3fb45ff 100644
--- a/test/rdoc/test_rdoc_generator_darkfish.rb
+++ b/test/rdoc/test_rdoc_generator_darkfish.rb
@@ -142,15 +142,6 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
@g.install_rdoc_static_file src, dst, options
assert_file dst
-
- begin
- assert_hard_link dst
- rescue MiniTest::Assertion
- return # hard links are not supported, no further tests needed
- end
-
- @g.install_rdoc_static_file src, dst, options
-
assert_hard_link dst
end
@@ -220,6 +211,21 @@ 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_template_stylesheets
+ css = Tempfile.create(%W'hoge .css', Dir.mktmpdir('tmp', '.'))
+ File.write(css, '')
+ css.close
+ base = File.basename(css)
+ refute_file(base)
+
+ @options.template_stylesheets << css
+
+ @g.generate
+
+ assert_file base
+ assert_include File.read('index.html'), %Q[href="./#{base}"]
+ end
+
##
# Asserts that +filename+ has a link count greater than 1 if hard links to
# @tmpdir are supported.
diff --git a/test/rdoc/test_rdoc_generator_json_index.rb b/test/rdoc/test_rdoc_generator_json_index.rb
index 66d15d1848f..6b69337b450 100644
--- a/test/rdoc/test_rdoc_generator_json_index.rb
+++ b/test/rdoc/test_rdoc_generator_json_index.rb
@@ -104,7 +104,7 @@ 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')
- # This is dirty hack on JRuby for MiniTest 4
+ # This is dirty hack on JRuby
assert orig_file.mtime.inspect == generated_file.mtime.inspect,
'.js files should be the same timestamp of original'
diff --git a/test/rdoc/test_rdoc_markup_to_html.rb b/test/rdoc/test_rdoc_markup_to_html.rb
index 342cf71082a..b2b21de8064 100644
--- a/test/rdoc/test_rdoc_markup_to_html.rb
+++ b/test/rdoc/test_rdoc_markup_to_html.rb
@@ -712,7 +712,7 @@ EXPECTED
def test_convert_underscore_adjacent_to_code
assert_equal "\n<p><code>aaa</code>_</p>\n", @to.convert(%q{+aaa+_})
- assert_equal "\n<p>`<code>i386-mswin32_</code><em>MSRTVERSION</em>&#39;</p>\n", @to.convert(%q{`+i386-mswin32_+_MSRTVERSION_'})
+ assert_equal "\n<p>\u{2018}<code>i386-mswin32_</code><em>MSRTVERSION</em>\u{2019}</p>\n", @to.convert(%q{`+i386-mswin32_+_MSRTVERSION_'})
end
def test_gen_url
diff --git a/test/rdoc/test_rdoc_options.rb b/test/rdoc/test_rdoc_options.rb
index f547f5bff3f..7c264c5e86b 100644
--- a/test/rdoc/test_rdoc_options.rb
+++ b/test/rdoc/test_rdoc_options.rb
@@ -632,6 +632,21 @@ rdoc_include:
$LOAD_PATH.replace orig_LOAD_PATH
end
+ def test_parse_template_stylesheets
+ css = nil
+ Dir.mktmpdir do |dir|
+ css = File.join(dir, "hoge.css")
+ File.write(css, "")
+ out, err = capture_output do
+ @options.parse %W[--template-stylesheets #{css}]
+ end
+
+ assert_empty out
+ assert_empty err
+ end
+ assert_include @options.template_stylesheets, css
+ end
+
def test_parse_visibility
@options.parse %w[--visibility=public]
assert_equal :public, @options.visibility
@@ -777,4 +792,62 @@ rdoc_include:
@options.visibility = :all
assert_equal :private, @options.visibility
end
+
+ def test_load_options
+ temp_dir do
+ options = RDoc::Options.new
+ options.markup = 'tomdoc'
+ options.write_options
+
+ options = RDoc::Options.load_options
+
+ assert_equal 'tomdoc', options.markup
+ end
+ end
+
+ def test_load_options_invalid
+ temp_dir do
+ File.open '.rdoc_options', 'w' do |io|
+ io.write "a: !ruby.yaml.org,2002:str |\nfoo"
+ end
+
+ e = assert_raise RDoc::Error do
+ RDoc::Options.load_options
+ end
+
+ options_file = File.expand_path '.rdoc_options'
+ assert_equal "#{options_file} is not a valid rdoc options file", e.message
+ end
+ end
+
+ def test_load_options_empty_file
+ temp_dir do
+ File.open '.rdoc_options', 'w' do |io|
+ end
+
+ options = RDoc::Options.load_options
+
+ assert_equal 'rdoc', options.markup
+ end
+ end
+
+ def test_load_options_partial_override
+ temp_dir do
+ File.open '.rdoc_options', 'w' do |io|
+ io.write "markup: Markdown"
+ end
+
+ options = RDoc::Options.load_options
+
+ assert_equal 'Markdown', options.markup
+ end
+ end
+
+ def load_options_no_file
+ temp_dir do
+ options = RDoc::Options.load_options
+
+ assert_kind_of RDoc::Options, options
+ end
+ end
end
diff --git a/test/rdoc/test_rdoc_parser_c.rb b/test/rdoc/test_rdoc_parser_c.rb
index 6601d28f606..8f51f32f261 100644
--- a/test/rdoc/test_rdoc_parser_c.rb
+++ b/test/rdoc/test_rdoc_parser_c.rb
@@ -1600,6 +1600,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 +1963,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
diff --git a/test/rdoc/test_rdoc_rdoc.rb b/test/rdoc/test_rdoc_rdoc.rb
index bb4573554cc..eaf92c8a9f5 100644
--- a/test/rdoc/test_rdoc_rdoc.rb
+++ b/test/rdoc/test_rdoc_rdoc.rb
@@ -106,64 +106,6 @@ class TestRDocRDoc < RDoc::TestCase
$stdin = STDIN
end
- def test_load_options
- temp_dir do
- options = RDoc::Options.new
- options.markup = 'tomdoc'
- options.write_options
-
- options = @rdoc.load_options
-
- assert_equal 'tomdoc', options.markup
- end
- end
-
- def test_load_options_invalid
- temp_dir do
- File.open '.rdoc_options', 'w' do |io|
- io.write "a: !ruby.yaml.org,2002:str |\nfoo"
- end
-
- e = assert_raise RDoc::Error do
- @rdoc.load_options
- end
-
- options_file = File.expand_path '.rdoc_options'
- assert_equal "#{options_file} is not a valid rdoc options file", e.message
- end
- end
-
- def test_load_options_empty_file
- temp_dir do
- File.open '.rdoc_options', 'w' do |io|
- end
-
- options = @rdoc.load_options
-
- assert_equal 'rdoc', options.markup
- end
- end
-
- def test_load_options_partial_override
- temp_dir do
- File.open '.rdoc_options', 'w' do |io|
- io.write "markup: Markdown"
- end
-
- options = @rdoc.load_options
-
- assert_equal 'Markdown', options.markup
- end
- end
-
- def load_options_no_file
- temp_dir do
- options = @rdoc.load_options
-
- assert_kind_of RDoc::Options, options
- end
- end
-
def test_normalized_file_list
test_path = File.expand_path(__FILE__)
files = temp_dir do |dir|
diff --git a/test/rdoc/test_rdoc_servlet.rb b/test/rdoc/test_rdoc_servlet.rb
index c41c2c8ae70..7a5b15a6ebd 100644
--- a/test/rdoc/test_rdoc_servlet.rb
+++ b/test/rdoc/test_rdoc_servlet.rb
@@ -1,5 +1,9 @@
# frozen_string_literal: true
require_relative 'helper'
+begin
+ require 'webrick'
+rescue LoadError
+end
class TestRDocServlet < RDoc::TestCase
diff --git a/test/rdoc/test_rdoc_text.rb b/test/rdoc/test_rdoc_text.rb
index 59d63b29bd0..a6b1597bbf7 100644
--- a/test/rdoc/test_rdoc_text.rb
+++ b/test/rdoc/test_rdoc_text.rb
@@ -485,6 +485,13 @@ The comments associated with
assert_equal '‘a’ ‘', to_html("'a' '")
end
+ def test_to_html_apostrophe_entity
+ assert_equal '‘a', to_html("&#39;a")
+ assert_equal 'a’', to_html("a&#39;")
+
+ assert_equal '‘a’ ‘', to_html("&#39;a&#39; &#39;")
+ end
+
def test_to_html_backslash
assert_equal 'S', to_html('\\S')
end
@@ -495,6 +502,7 @@ The comments associated with
def test_to_html_copyright
assert_equal '©', to_html('(c)')
+ assert_equal '©', to_html('(C)')
end
def test_to_html_dash
@@ -507,6 +515,7 @@ The comments associated with
def test_to_html_double_backtick
assert_equal '“a', to_html('``a')
assert_equal '“a“', to_html('``a``')
+ assert_equal '“a”', to_html("``a''")
end
def test_to_html_double_quote
@@ -549,6 +558,7 @@ The comments associated with
def test_to_html_registered_trademark
assert_equal '®', to_html('(r)')
+ assert_equal '®', to_html('(R)')
end
def test_to_html_tt_tag
diff --git a/test/readline/test_readline.rb b/test/readline/test_readline.rb
index 59408c2b111..a0438aa1fdf 100644
--- a/test/readline/test_readline.rb
+++ b/test/readline/test_readline.rb
@@ -3,11 +3,14 @@ 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
@@ -449,7 +452,7 @@ module BasetestReadline
w << "\cr\u3042\u3093"
w.reopen(IO::NULL)
assert_equal("\u3046\u3093", Readline.readline("", true), bug6602)
- Timeout.timeout(2) do
+ Timeout.timeout(TIMEOUT) do
assert_equal("\u3042\u3093", Readline.readline("", true), bug6602)
end
assert_equal(nil, Readline.readline("", true), bug6602)
@@ -475,6 +478,98 @@ module BasetestReadline
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=)
@@ -715,6 +810,20 @@ module BasetestReadline
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)
diff --git a/test/reline/helper.rb b/test/reline/helper.rb
index d8d4540797d..cd3783ddb86 100644
--- a/test/reline/helper.rb
+++ b/test/reline/helper.rb
@@ -1,4 +1,7 @@
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
+
+ENV['TERM'] = 'xterm' # for some CI environments
+
require 'reline'
require 'test/unit'
diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb
index 087fd1d1532..8053225d244 100644
--- a/test/reline/test_key_actor_emacs.rb
+++ b/test/reline/test_key_actor_emacs.rb
@@ -5,6 +5,7 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
Reline.send(:test_mode)
@prompt = '> '
@config = Reline::Config.new # Emacs mode is default
+ @config.autocompletion = false
Reline::HISTORY.instance_variable_set(:@config, @config)
Reline::HISTORY.clear
@encoding = Reline::IOGate.encoding
@@ -2284,6 +2285,27 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_line(' 12345')
end
+ def test_ignore_NUL_by_ed_quoted_insert
+ input_keys(%Q{"\C-v\C-@"}, false)
+ assert_byte_pointer_size('""')
+ assert_cursor(2)
+ assert_cursor_max(2)
+ end
+
+ def test_ed_argument_digit_by_meta_num
+ input_keys('abcdef')
+ assert_byte_pointer_size('abcdef')
+ assert_cursor(6)
+ assert_cursor_max(6)
+ assert_line('abcdef')
+ input_keys("\M-2", false)
+ input_keys("\C-h", false)
+ assert_byte_pointer_size('abcd')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ assert_line('abcd')
+ end
+
def test_input_unknown_char
input_keys('͸') # U+0378 (unassigned)
assert_line('͸')
diff --git a/test/reline/test_key_actor_vi.rb b/test/reline/test_key_actor_vi.rb
index 9455c08e2b9..722cdc0b75f 100644
--- a/test/reline/test_key_actor_vi.rb
+++ b/test/reline/test_key_actor_vi.rb
@@ -987,11 +987,6 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_cursor_max(3)
assert_line('foo')
input_keys("\C-n")
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
- input_keys("\C-n")
assert_byte_pointer_size('foo_bar')
assert_cursor(7)
assert_cursor_max(7)
@@ -1012,11 +1007,6 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_cursor_max(7)
assert_line('foo_bar')
input_keys("_\C-n")
- assert_byte_pointer_size('foo_bar_')
- assert_cursor(8)
- assert_cursor_max(8)
- assert_line('foo_bar_')
- input_keys("\C-n")
assert_byte_pointer_size('foo_bar_baz')
assert_cursor(11)
assert_cursor_max(11)
@@ -1043,11 +1033,6 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_cursor_max(3)
assert_line('foo')
input_keys("\C-p")
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
- input_keys("\C-p")
assert_byte_pointer_size('foo_bar_baz')
assert_cursor(11)
assert_cursor_max(11)
@@ -1068,11 +1053,6 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_cursor_max(11)
assert_line('foo_bar_baz')
input_keys("\C-h\C-p")
- assert_byte_pointer_size('foo_bar_ba')
- assert_cursor(10)
- assert_cursor_max(10)
- assert_line('foo_bar_ba')
- input_keys("\C-p")
assert_byte_pointer_size('foo_bar_baz')
assert_cursor(11)
assert_cursor_max(11)
@@ -1096,11 +1076,6 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
input_keys('abcde fo ABCDE')
assert_line('abcde fo ABCDE')
input_keys("\C-[" + 'h' * 5 + "i\C-n")
- assert_byte_pointer_size('abcde fo')
- assert_cursor(8)
- assert_cursor_max(14)
- assert_line('abcde fo ABCDE')
- input_keys("\C-n")
assert_byte_pointer_size('abcde foo_bar')
assert_cursor(13)
assert_cursor_max(19)
@@ -1121,11 +1096,6 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_cursor_max(19)
assert_line('abcde foo_bar 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')
- input_keys("\C-n")
assert_byte_pointer_size('abcde foo_bar_baz')
assert_cursor(17)
assert_cursor_max(23)
diff --git a/test/reline/test_key_stroke.rb b/test/reline/test_key_stroke.rb
index 15675a9b5ab..d377a1e9726 100644
--- a/test/reline/test_key_stroke.rb
+++ b/test/reline/test_key_stroke.rb
@@ -36,7 +36,7 @@ class Reline::KeyStroke::Test < Reline::TestCase
assert_equal(:matched, stroke.match_status("abzwabk".bytes))
end
- def test_aaa
+ def test_expand
config = Reline::Config.new
{
'abc' => '123',
@@ -46,4 +46,34 @@ class Reline::KeyStroke::Test < Reline::TestCase
stroke = Reline::KeyStroke.new(config)
assert_equal('123'.bytes, stroke.expand('abc'.bytes))
end
+
+ def test_oneshot_key_bindings
+ config = Reline::Config.new
+ {
+ 'abc' => '123',
+ }.each_pair do |key, func|
+ 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))
+ 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',
+ [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]))
+ end
end
diff --git a/test/reline/test_reline.rb b/test/reline/test_reline.rb
index 161b329740f..dd049ac1270 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
@@ -246,29 +247,57 @@ 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::IOGate}"
+ 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
@@ -281,10 +310,6 @@ class Reline::Test < Reline::TestCase
assert_equal(Reline::KeyActor::Emacs, Reline.send(:core).config.editing_mode.class)
end
- def test_editing_mode
- # TODO
- end
-
def test_readmultiline
# readmultiline is module function
assert_include(Reline.methods, :readmultiline)
diff --git a/test/reline/test_reline_key.rb b/test/reline/test_reline_key.rb
new file mode 100644
index 00000000000..fb700a6f2eb
--- /dev/null
+++ b/test/reline/test_reline_key.rb
@@ -0,0 +1,53 @@
+require_relative 'helper'
+require "reline"
+
+class Reline::TestKey < Reline::TestCase
+ def setup
+ end
+
+ def teardown
+ Reline.test_reset
+ end
+
+ def test_match_key
+ assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 2, false)))
+ assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(nil, 2, false)))
+ assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 2, nil)))
+
+ assert(Reline::Key.new(nil, 2, false).match?(Reline::Key.new(nil, 2, false)))
+ assert(Reline::Key.new(1, nil, false).match?(Reline::Key.new(1, nil, false)))
+ assert(Reline::Key.new(1, 2, nil).match?(Reline::Key.new(1, 2, nil)))
+
+ assert(Reline::Key.new(nil, 2, false).match?(Reline::Key.new(nil, 2, false)))
+ assert(Reline::Key.new(1, nil, false).match?(Reline::Key.new(1, nil, false)))
+ assert(Reline::Key.new(1, 2, nil).match?(Reline::Key.new(1, 2, nil)))
+
+ assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(3, 1, false)))
+ assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 3, false)))
+ assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 3, true)))
+ end
+
+ def test_match_integer
+ assert(Reline::Key.new(1, 2, false).match?(2))
+ assert(Reline::Key.new(nil, 2, false).match?(2))
+ assert(Reline::Key.new(1, nil, false).match?(1))
+
+ assert(!Reline::Key.new(1, 2, false).match?(1))
+ assert(!Reline::Key.new(1, nil, false).match?(2))
+ assert(!Reline::Key.new(nil, nil, false).match?(1))
+ end
+
+ def test_match_symbol
+ assert(Reline::Key.new(:key1, :key2, false).match?(:key2))
+ assert(Reline::Key.new(:key1, nil, false).match?(:key1))
+
+ assert(!Reline::Key.new(:key1, :key2, false).match?(:key1))
+ assert(!Reline::Key.new(:key1, nil, false).match?(:key2))
+ assert(!Reline::Key.new(nil, nil, false).match?(:key1))
+ end
+
+ def test_match_other
+ assert(!Reline::Key.new(:key1, 2, false).match?("key1"))
+ assert(!Reline::Key.new(nil, nil, false).match?(nil))
+ end
+end
diff --git a/test/reline/test_terminfo.rb b/test/reline/test_terminfo.rb
index 6f98591b159..f1bf1979312 100644
--- a/test/reline/test_terminfo.rb
+++ b/test/reline/test_terminfo.rb
@@ -8,17 +8,25 @@ class Reline::Terminfo::Test < Reline::TestCase
def test_tigetstr
assert Reline::Terminfo.tigetstr('khome')
+ rescue Reline::Terminfo::TerminfoError => e
+ skip e.message
end
def test_tiparm
assert Reline::Terminfo.tigetstr('khome').tiparm
+ rescue Reline::Terminfo::TerminfoError => e
+ skip e.message
end
def test_tigetstr_with_param
assert Reline::Terminfo.tigetstr('cuu').include?('%p1%d')
+ rescue Reline::Terminfo::TerminfoError => e
+ skip 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
end
end if Reline::Terminfo.enabled?
diff --git a/test/reline/test_unicode.rb b/test/reline/test_unicode.rb
index 08f8197cefa..1233e034e84 100644
--- a/test/reline/test_unicode.rb
+++ b/test/reline/test_unicode.rb
@@ -17,4 +17,9 @@ class Reline::Unicode::Test < Reline::TestCase
def test_ambiguous_width
assert_equal 2, Reline::Unicode.calculate_width('√', true)
end
+
+ def test_take_range
+ assert_equal 'cdef', Reline::Unicode.take_range('abcdefghi', 2, 4)
+ assert_equal 'いう', Reline::Unicode.take_range('あいうえお', 2, 4)
+ end
end
diff --git a/test/reline/windows/test_key_event_record.rb b/test/reline/windows/test_key_event_record.rb
index 60dae3e3f85..a034d20fe44 100644
--- a/test/reline/windows/test_key_event_record.rb
+++ b/test/reline/windows/test_key_event_record.rb
@@ -1,5 +1,5 @@
require_relative '../helper'
-require 'reline/windows'
+return unless Reline.const_defined?(:Windows)
class Reline::Windows
class KeyEventRecord::Test < Reline::TestCase
diff --git a/test/reline/yamatanooroti/multiline_repl b/test/reline/yamatanooroti/multiline_repl
index f2efdd4eafb..da886b8f06f 100755
--- a/test/reline/yamatanooroti/multiline_repl
+++ b/test/reline/yamatanooroti/multiline_repl
@@ -30,6 +30,113 @@ opt.on('--dynamic-prompt-returns-empty') {
opt.on('--auto-indent') {
AutoIndent.new
}
+opt.on('--dialog VAL') { |v|
+ Reline.add_dialog_proc(:simple_dialog, lambda {
+ return nil if v.include?('nil')
+ if v.include?('simple')
+ contents = <<~RUBY.split("\n")
+ 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.
+ RUBY
+ elsif v.include?('long')
+ contents = <<~RUBY.split("\n")
+ 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.
+ RUBY
+ elsif v.include?('fullwidth')
+ contents = <<~RUBY.split("\n")
+ Rubyとは...
+
+ オープンソースの動的なプログラミン
+ グ言語で、シンプルさと高い生産性を
+ 備えています。エレガントな文法を持
+ ち、自然に読み書きができます。
+ RUBY
+ end
+ if v.include?('scrollkey')
+ dialog.trap_key = nil
+ if key and key.match?(dialog.name)
+ if dialog.pointer.nil?
+ dialog.pointer = 0
+ elsif dialog.pointer >= (contents.size - 1)
+ dialog.pointer = 0
+ else
+ dialog.pointer += 1
+ end
+ end
+ dialog.trap_key = [?j.ord]
+ height = 4
+ end
+ scrollbar = false
+ if v.include?('scrollbar')
+ scrollbar = true
+ end
+ if v.include?('alt-scrollbar')
+ scrollbar = true
+ end
+ Reline::DialogRenderInfo.new(pos: cursor_pos, contents: contents, height: height, scrollbar: scrollbar)
+ })
+ 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('--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-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) }
+ }
+}
+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.parse!(ARGV)
begin
diff --git a/test/reline/yamatanooroti/termination_checker.rb b/test/reline/yamatanooroti/termination_checker.rb
index a36e075bdeb..9c2c3ae740e 100644
--- a/test/reline/yamatanooroti/termination_checker.rb
+++ b/test/reline/yamatanooroti/termination_checker.rb
@@ -20,7 +20,7 @@ end
class AutoIndent < RubyLex
def initialize
set_input(self)
- context = Struct.new(:auto_indent_mode).new(true)
+ context = Struct.new(:auto_indent_mode, :workspace).new(true, nil)
set_auto_indent(context)
end
diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb
index d2e73ca8cbf..e1dde835896 100644
--- a/test/reline/yamatanooroti/test_rendering.rb
+++ b/test/reline/yamatanooroti/test_rendering.rb
@@ -290,7 +290,6 @@ begin
end
def test_clear_multiline_and_autowrap
- omit # FIXME clear logic is buggy
start_terminal(10, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("def aaaaaa\n 3\n\C-lend")
close
@@ -425,10 +424,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.
@@ -731,7 +730,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)
@@ -741,7 +740,7 @@ begin
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
@@ -753,63 +752,427 @@ 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")
+ def test_with_newline
+ omit if Reline::IOGate.win?
+ cmd = %Q{ruby -e 'print(%Q{abc def \\e\\r})' | ruby -I#{@pwd}/lib -rreline -e 'p Reline.readline(%{> })'}
+ start_terminal(40, 50, ['bash', '-c', cmd])
+ close
+ assert_screen(<<~'EOC')
+ > abc def
+ "abc def "
+ 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")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> aaa Ybbb Xccc ddd
+ EOC
+ end
+
+ def test_completion_journey_2nd_line
+ write_inputrc <<~LINES
+ set editing-mode vi
+ LINES
+ start_terminal(10, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete}, startup_message: 'Multiline REPL.')
+ write("def hoge\n S\C-n")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> def hoge
+ prompt> String
+ EOC
+ end
+
+ def test_completion_journey_with_empty_line
+ write_inputrc <<~LINES
+ set editing-mode vi
+ LINES
+ start_terminal(10, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete}, startup_message: 'Multiline REPL.')
+ write("\C-n\C-p")
close
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>
EOC
end
- def test_brackets
- omit unless Reline::IOGate.win?
- start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
- write("\x80\M-[\x80\M-{\x80\M-}\x80\M-]\n")
+ 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")
close
- assert_screen(<<~EOC)
+ 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
+
+ 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")
+ close
+ assert_screen(<<~'EOC')
Multiline REPL.
- prompt> [{}]
- => [{}]
+ 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
+
+ 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 ")
+ write('S')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> def hoge
+ prompt>
prompt>
+ prompt> String
+ prompt> Struct
+ prompt> Symbol
+ prompt> ScriptError
+ prompt> SyntaxError
+ prompt> Signal
+ prompt> S
+ prompt> end
EOC
end
- def test_with_newline
- omit if Reline::IOGate.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])
+ def test_autocomplete_return_to_original
+ start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write('S')
+ write('t')
+ write('r')
+ 3.times{ write("\C-i") }
close
assert_screen(<<~'EOC')
- > abc def
- "abc def "
+ Multiline REPL.
+ prompt> Str
+ String
+ Struct
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")
+ def test_autocomplete_target_is_wrapped
+ start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write(' ')
+ write('S')
+ write('t')
+ write('r')
close
assert_screen(<<~'EOC')
Multiline REPL.
- prompt> aaa Ybbb Xccc ddd
+ prompt> St
+ r String
+ Struct
+ EOC
+ end
+
+ def test_simple_dialog_with_scroll_key
+ start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog long,scrollkey}, startup_message: 'Multiline REPL.')
+ write('a')
+ 5.times{ write('j') }
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> a
+ A dynamic, open
+ source programming
+ language with a
+ focus on simplicity
+ EOC
+ end
+
+ def test_simple_dialog_scrollbar_with_moving_to_right
+ start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog long,scrollkey,scrollbar}, startup_message: 'Multiline REPL.')
+ 6.times{ write('j') }
+ write('a')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> a
+ source programming ▄
+ language with a █
+ focus on simplicity
+ and productivity.
+ EOC
+ end
+
+ def test_simple_dialog_scrollbar_with_moving_to_left
+ start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog long,scrollkey,scrollbar}, startup_message: 'Multiline REPL.')
+ write('a')
+ 6.times{ write('j') }
+ write("\C-h")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt>
+ source programming ▄
+ language with a █
+ focus on simplicity
+ and productivity.
+ EOC
+ end
+
+ def test_dialog_with_fullwidth_chars
+ ENV['RELINE_TEST_PROMPT'] = '> '
+ start_terminal(30, 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(30, 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')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> Street
+ EOC
+ end
+
+ def test_autocomplete
+ start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write('Str')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> Str
+ String
+ Struct
+ 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")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> def hoge
+ prompt> Str
+ String
+ Struct
+ EOC
+ end
+
+ def test_autocomplete_rerender_under_dialog
+ start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("def hoge\n\n 123456\n 456789\nend\C-p\C-p\C-p a = Str")
+ write('i')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> def hoge
+ prompt> a = Stri
+ prompt> 1234String
+ prompt> 456789
+ prompt> end
+ 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')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> S
+ String █
+ Struct █
+ Symbol █
+ StopIteration █
+ SystemCallError █
+ SystemExit █
+ SystemStackError█
+ ScriptError █
+ SyntaxError █
+ Signal █
+ SizedQueue █
+ Set
+ SecureRandom
+ Socket
+ StringIO
+ EOC
+ end
+
+ def test_autocomplete_long_with_scrollbar_scroll
+ start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-long}, startup_message: 'Multiline REPL.')
+ write('S' + "\C-i" * 16)
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> StringScanner
+ Struct ▄
+ Symbol █
+ StopIteration █
+ SystemCallError █
+ SystemExit █
+ SystemStackError█
+ ScriptError █
+ SyntaxError █
+ Signal █
+ SizedQueue █
+ Set █
+ SecureRandom ▀
+ Socket
+ StringIO
+ StringScanner
+ 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')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> a
+ 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
- private def write_inputrc(content)
+ def write_inputrc(content)
File.open(@inputrc_file, 'w') do |f|
f.write content
end
diff --git a/test/ripper/test_ripper.rb b/test/ripper/test_ripper.rb
index ab841b7616c..76276c54eff 100644
--- a/test/ripper/test_ripper.rb
+++ b/test/ripper/test_ripper.rb
@@ -75,6 +75,15 @@ class TestRipper::Ripper < Test::Unit::TestCase
assert_include out.string[/.*"local variable or method".*/], 'test_xxxx'
end
+ def test_yydebug_string
+ out = StringIO.new
+ ripper = Ripper.new '"woot"'
+ ripper.yydebug = true
+ ripper.debug_output = out
+ ripper.parse
+ assert_include out.string[/.*"literal content".*/], 'woot'
+ end
+
def test_regexp_with_option
bug11932 = '[ruby-core:72638] [Bug #11932]'
src = '/[\xC0-\xF0]/u'.dup.force_encoding(Encoding::UTF_8)
diff --git a/test/ripper/test_sexp.rb b/test/ripper/test_sexp.rb
index b4e70fa4f51..9faeaba7823 100644
--- a/test/ripper/test_sexp.rb
+++ b/test/ripper/test_sexp.rb
@@ -520,4 +520,18 @@ eot
assert_raise(SyntaxError) { Ripper.sexp('def req(true) end', raise_errors: true) }
assert_raise(SyntaxError) { Ripper.sexp_raw('def req(true) end', raise_errors: true) }
end
+
+ def test_hash_value_omission
+ sexp = Ripper.sexp("{x: 1, y:}")
+ assoclist = search_sexp(:assoclist_from_args, sexp)
+ x = assoclist[1][0]
+ assert_equal(:@label, x[1][0])
+ assert_equal("x:", x[1][1])
+ assert_equal(:@int, x[2][0])
+ assert_equal("1", x[2][1])
+ y = assoclist[1][1]
+ assert_equal(:@label, y[1][0])
+ assert_equal("y:", y[1][1])
+ assert_equal(nil, y[2])
+ end
end if ripper_test
diff --git a/test/ruby/enc/test_emoji_breaks.rb b/test/ruby/enc/test_emoji_breaks.rb
index 1d58e43ffa5..cdde4da9bf2 100644
--- a/test/ruby/enc/test_emoji_breaks.rb
+++ b/test/ruby/enc/test_emoji_breaks.rb
@@ -13,7 +13,7 @@ class TestEmojiBreaks::BreakTest
@filename = filename
@line_number = line_number
@comment = comment.gsub(/\s+/, ' ').strip
- if filename=='emoji-test'
+ if filename=='emoji-test' or filename=='emoji-variation-sequences'
codes, @type = data.split(/\s*;\s*/)
@shortname = ''
else
@@ -83,16 +83,16 @@ TestEmojiBreaks.data_files_available? and class TestEmojiBreaks
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 /\A(#|\z)/.match? line
+ 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('#')) rescue 'whatever'
+ file_tests << BreakTest.new(file.basename, $., *(code_point.to_s(16)+rest).split('#', 2))
end
else
- file_tests << BreakTest.new(file.basename, $., *line.split('#')) rescue 'whatever'
+ file_tests << BreakTest.new(file.basename, $., *line.split('#', 2))
end
end
raise "File Version Mismatch: file: #{file.fullname}, version: #{file.version}" if version_mismatch
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index 7922e5ad079..e3bd1cd075c 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -1110,4 +1110,23 @@ class TestArgf < Test::Unit::TestCase
assert_raise(TypeError, bug11610) {gets}
};
end
+
+ def test_sized_read
+ s = "a"
+ [@t1, @t2, @t3].each { |t|
+ File.binwrite(t.path, s)
+ s = s.succ
+ }
+
+ ruby('-e', "print ARGF.read(3)", @t1.path, @t2.path, @t3.path) do |f|
+ assert_equal("abc", f.read)
+ end
+
+ argf = ARGF.class.new(@t1.path, @t2.path, @t3.path)
+ begin
+ assert_equal("abc", argf.read(3))
+ ensure
+ argf.close
+ end
+ end
end
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 8f05f9cebd9..a97a9c25580 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -652,8 +652,17 @@ class TestArray < Test::Unit::TestCase
b.concat(b, b)
assert_equal([4, 5, 4, 5, 4, 5], b)
- assert_raise(TypeError) { [0].concat(:foo) }
- assert_raise(FrozenError) { [0].freeze.concat(:foo) }
+ assert_raise(TypeError) { @cls[0].concat(:foo) }
+ assert_raise(FrozenError) { @cls[0].freeze.concat(:foo) }
+
+ a = @cls[nil]
+ def (x = Object.new).to_ary
+ ary = Array.new(2)
+ ary << [] << [] << :ok
+ end
+ EnvUtil.under_gc_stress {a.concat(x)}
+ GC.start
+ assert_equal(:ok, a.last)
end
def test_count
@@ -1576,6 +1585,8 @@ class TestArray < Test::Unit::TestCase
assert_nil(a.slice(10, -3))
assert_equal @cls[], a.slice(10..7)
+
+ assert_equal([100], a.slice(-1, 1_000_000_000))
end
def test_slice!
@@ -1624,6 +1635,21 @@ class TestArray < Test::Unit::TestCase
assert_raise(ArgumentError) { @cls[1].slice!(0, 0, 0) }
end
+ def test_slice_out_of_range!
+ a = @cls[*(1..100).to_a]
+
+ assert_nil(a.clone.slice!(-101..-1))
+ assert_nil(a.clone.slice!(-101..))
+
+ # assert_raise_with_message(RangeError, "((-101..-1).%(2)) out of range") { a.clone.slice!((-101..-1)%2) }
+ # assert_raise_with_message(RangeError, "((-101..).%(2)) out of range") { a.clone.slice!((-101..)%2) }
+
+ assert_nil(a.clone.slice!(10, -3))
+ assert_equal @cls[], a.clone.slice!(10..7)
+
+ assert_equal([100], a.clone.slice!(-1, 1_000_000_000))
+ end
+
def test_sort
a = @cls[ 4, 1, 2, 3 ]
assert_equal(@cls[1, 2, 3, 4], a.sort)
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index 3b4cbc7dee8..953c8435c33 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -231,6 +231,11 @@ class TestAst < Test::Unit::TestCase
assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) }
end
+ def test_of_c_method
+ c = Class.new { attr_reader :foo }
+ assert_nil(RubyVM::AbstractSyntaxTree.of(c.instance_method(:foo)))
+ end
+
def test_scope_local_variables
node = RubyVM::AbstractSyntaxTree.parse("_x = 0")
lv, _, body = *node.children
@@ -393,8 +398,8 @@ class TestAst < Test::Unit::TestCase
assert_equal(:a, args.children[rest])
end
- def test_save_script_lines_for_parse
- node = RubyVM::AbstractSyntaxTree.parse(<<~END, save_script_lines: true)
+ def test_keep_script_lines_for_parse
+ node = RubyVM::AbstractSyntaxTree.parse(<<~END, keep_script_lines: true)
1.times do
2.times do
end
@@ -432,14 +437,14 @@ dummy
assert_equal(expected, node.children.last.children.last.children.last.source)
end
- def test_save_script_lines_for_of
+ def test_keep_script_lines_for_of
proc = Proc.new { 1 + 2 }
method = self.method(__method__)
- node_proc = RubyVM::AbstractSyntaxTree.of(proc, save_script_lines: true)
- node_method = RubyVM::AbstractSyntaxTree.of(method, save_script_lines: true)
+ node_proc = RubyVM::AbstractSyntaxTree.of(proc, keep_script_lines: true)
+ node_method = RubyVM::AbstractSyntaxTree.of(method, keep_script_lines: true)
assert_equal("{ 1 + 2 }", node_proc.source)
- assert_equal("def test_save_script_lines_for_of\n", node_method.source.lines.first)
+ assert_equal("def test_keep_script_lines_for_of\n", node_method.source.lines.first)
end
end
diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb
index 98d513da87e..7709760d199 100644
--- a/test/ruby/test_autoload.rb
+++ b/test/ruby/test_autoload.rb
@@ -456,6 +456,31 @@ 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)
+ 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 +488,7 @@ 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
end
diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb
index 742463a04db..aa79db24cb0 100644
--- a/test/ruby/test_backtrace.rb
+++ b/test/ruby/test_backtrace.rb
@@ -170,6 +170,34 @@ class TestBacktrace < Test::Unit::TestCase
end
end
+ def test_caller_limit_cfunc_iseq_no_pc
+ def self.a; [1].group_by { b } end
+ def self.b
+ [
+ caller_locations(2, 1).first.base_label,
+ caller_locations(3, 1).first.base_label
+ ]
+ end
+ assert_equal({["each", "group_by"]=>[1]}, a)
+ end
+
+ def test_caller_location_inspect_cfunc_iseq_no_pc
+ def self.foo
+ @res = caller_locations(2, 1).inspect
+ end
+ @line = __LINE__ + 1
+ 1.times.map { 1.times.map { foo } }
+ assert_equal("[\"#{__FILE__}:#{@line}:in `times'\"]", @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 } }
+ assert_equal(__FILE__, @res)
+ end
+
def test_caller_locations
cs = caller(0); locs = caller_locations(0).map{|loc|
loc.to_s
diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb
index 368c046261e..96bca08601c 100644
--- a/test/ruby/test_class.rb
+++ b/test/ruby/test_class.rb
@@ -737,4 +737,22 @@ class TestClass < Test::Unit::TestCase
c = Class.new.freeze
assert_same(c, Module.new.const_set(:Foo, c))
end
+
+ def test_descendants
+ 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, ssc], c.descendants)
+ assert_equal([ssc], sc.descendants)
+ assert_equal([], ssc.descendants)
+
+ object_descendants = Object.descendants
+ assert_include(object_descendants, c)
+ assert_include(object_descendants, sc)
+ assert_include(object_descendants, ssc)
+ end
end
diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb
index 4674f984ffb..702c332cd22 100644
--- a/test/ruby/test_enum.rb
+++ b/test/ruby/test_enum.rb
@@ -731,6 +731,8 @@ 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) { })
end
def test_each_cons
@@ -750,6 +752,8 @@ 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) { })
end
def test_zip
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index 4342c10d026..c823b79c6d1 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -79,7 +79,7 @@ class TestEnumerator < Test::Unit::TestCase
assert_raise(NoMethodError) { enum.each {} }
enum.freeze
assert_raise(ArgumentError) {
- capture_io do
+ capture_output do
# warning: Enumerator.new without a block is deprecated; use Object#to_enum
enum.__send__(:initialize, @obj, :foo)
end
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index 583b432e3d3..ea0f367334f 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -503,15 +503,15 @@ class TestEnv < Test::Unit::TestCase
end
def test_huge_value
- huge_value = "bar" * 40960
- ENV["foo"] = "bar"
- if /mswin/ =~ RUBY_PLATFORM
- assert_raise(Errno::EINVAL) { ENV["foo"] = huge_value }
- assert_equal("bar", ENV["foo"])
+ if /mswin/ =~ RUBY_PLATFORM || /ucrt/ =~ RbConfig::CONFIG['sitearch']
+ # On Windows >= Vista each environment variable can be max 32768 characters
+ huge_value = "bar" * 10900
else
- assert_nothing_raised { ENV["foo"] = huge_value }
- assert_equal(huge_value, ENV["foo"])
+ huge_value = "bar" * 40960
end
+ ENV["foo"] = "overwritten"
+ assert_nothing_raised { ENV["foo"] = huge_value }
+ assert_equal(huge_value, ENV["foo"])
end
if /mswin|mingw/ =~ RUBY_PLATFORM
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 4abbb4cf6f0..67f38c2e91a 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -561,6 +561,7 @@ end.join
end
def test_ensure_after_nomemoryerror
+ skip "Forcing NoMemoryError causes problems in some environments"
assert_separately([], "$_ = 'a' * 1_000_000_000_000_000_000")
rescue NoMemoryError
assert_raise(NoMemoryError) do
@@ -576,7 +577,7 @@ end.join
end
end;
end
- rescue Minitest::Assertion
+ rescue Test::Unit::AssertionFailedError
# Possibly compiled with -DRUBY_DEBUG, in which
# case rb_bug is used instead of NoMemoryError,
# and we cannot test ensure after NoMemoryError.
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index 70966d83a4a..9dd05f6c934 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
@@ -493,6 +506,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)
@@ -1454,6 +1470,7 @@ class TestFileExhaustive < Test::Unit::TestCase
fn1,
zerofile,
notownedfile,
+ grpownedfile,
suidfile,
sgidfile,
stickyfile,
@@ -1689,6 +1706,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
diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
index 7d8bde04f84..46683d0ed57 100644
--- a/test/ruby/test_gc_compact.rb
+++ b/test/ruby/test_gc_compact.rb
@@ -69,10 +69,11 @@ class TestGCCompact < Test::Unit::TestCase
}
count = GC.stat :compact_count
GC.auto_compact = true
- loop do
+ n = 1_000_000
+ n.times do
break if count < GC.stat(:compact_count)
list2 << Object.new
- end
+ end and skip "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?
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index 028610ea67b..f79879c20a5 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -1278,6 +1278,15 @@ 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
@@ -2048,21 +2057,12 @@ class TestHash < Test::Unit::TestCase
class TestSubHash < TestHash
class SubHash < Hash
- def reject(*)
- super
- end
end
def setup
@cls = SubHash
super
end
-
- def test_reject
- assert_warning(/extra states are no longer copied/) do
- super
- end
- end
end
ruby2_keywords def get_flagged_hash(*args)
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb
index 1cd256a1cf5..9354514df07 100644
--- a/test/ruby/test_integer.rb
+++ b/test/ruby/test_integer.rb
@@ -576,6 +576,8 @@ class TestInteger < Test::Unit::TestCase
assert_equal([0, 9, 8, 7, 6, 5, 4, 3, 2, 1], 1234567890.digits)
assert_equal([90, 78, 56, 34, 12], 1234567890.digits(100))
assert_equal([10, 5, 6, 8, 0, 10, 8, 6, 1], 1234567890.digits(13))
+ assert_equal((2 ** 1024).to_s(7).chars.map(&:to_i).reverse, (2 ** 1024).digits(7))
+ assert_equal([0] * 100 + [1], (2 ** (128 * 100)).digits(2 ** 128))
end
def test_digits_for_negative_numbers
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index f7240c4cf60..a90140fd0b3 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -3991,6 +3991,18 @@ __END__
}
end
+ def test_marshal_closed_io
+ bug18077 = '[ruby-core:104927] [Bug #18077]'
+ r, w = IO.pipe
+ r.close; w.close
+ assert_raise(TypeError, bug18077) {Marshal.dump(r)}
+
+ class << r
+ undef_method :closed?
+ end
+ assert_raise(TypeError, bug18077) {Marshal.dump(r)}
+ end
+
def test_stdout_to_closed_pipe
EnvUtil.invoke_ruby(["-e", "loop {puts :ok}"], "", true, true) do
|in_p, out_p, err_p, pid|
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index 0cde1fbb7a5..edd131823e2 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -95,6 +95,16 @@ class TestISeq < Test::Unit::TestCase
assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
end
+ def test_lambda_with_ractor_roundtrip
+ iseq = compile(<<~EOF)
+ x = 42
+ y = lambda { x }
+ Ractor.make_shareable(y)
+ y.call
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+ end
+
def test_disasm_encoding
src = "\u{3042} = 1; \u{3042}; \u{3043}"
asm = compile(src).disasm
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 5b79f8c0ea3..669dcf56e6f 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -10,6 +10,7 @@ class TestJIT < Test::Unit::TestCase
IGNORABLE_PATTERNS = [
/\AJIT recompile: .+\n\z/,
/\AJIT inline: .+\n\z/,
+ /\AJIT cancel: .+\n\z/,
/\ASuccessful MJIT finish\n\z/,
]
MAX_CACHE_PATTERNS = [
@@ -52,8 +53,9 @@ class TestJIT < Test::Unit::TestCase
# ruby -w -Itest/lib test/ruby/test_jit.rb
if $VERBOSE
+ pid = $$
at_exit do
- unless TestJIT.untested_insns.empty?
+ if pid == $$ && !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
@@ -607,6 +609,17 @@ class TestJIT < Test::Unit::TestCase
assert_eval_with_jit('print "\x00".unpack("c")', stdout: '[0]', success_count: 1)
end
+ def test_compile_insn_checkmatch
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch])
+ begin;
+ ary = %w(hello good-bye)
+ case 'hello'
+ when *ary
+ 'world'
+ end
+ end;
+ 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)
@@ -1100,6 +1113,22 @@ class TestJIT < Test::Unit::TestCase
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;
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index c8191a722c9..9094259bc27 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -4351,4 +4351,21 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_raise(TypeError, bug16603) { p(**42) }
assert_raise(TypeError, bug16603) { p(k:1, **42) }
end
+
+ def test_value_omission
+ f = ->(**kwargs) { kwargs }
+ x = 1
+ y = 2
+ assert_equal({x: 1, y: 2}, f.call(x:, y:))
+ assert_equal({x: 1, y: 2, z: 3}, f.call(x:, y:, z: 3))
+ assert_equal({one: 1, two: 2}, f.call(one:, two:))
+ end
+
+ private def one
+ 1
+ end
+
+ private def two
+ 2
+ end
end
diff --git a/test/ruby/test_literal.rb b/test/ruby/test_literal.rb
index 579a39dee80..8c3256c0346 100644
--- a/test/ruby/test_literal.rb
+++ b/test/ruby/test_literal.rb
@@ -474,6 +474,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',
@@ -506,6 +517,30 @@ class TestRubyLiteral < Test::Unit::TestCase
assert_equal(100, h['a'])
end
+ FOO = "foo"
+
+ def test_hash_value_omission
+ x = 1
+ y = 2
+ assert_equal({x: 1, y: 2}, {x:, y:})
+ assert_equal({x: 1, y: 2, z: 3}, {x:, y:, z: 3})
+ assert_equal({one: 1, two: 2}, {one:, two:})
+ b = binding
+ b.local_variable_set(:if, "if")
+ b.local_variable_set(:self, "self")
+ assert_equal({FOO: "foo", if: "if", self: "self"},
+ eval('{FOO:, if:, self:}', b))
+ assert_syntax_error('{"#{x}":}', /'\}'/)
+ end
+
+ private def one
+ 1
+ end
+
+ private def two
+ 2
+ end
+
def test_range
assert_instance_of Range, (1..2)
assert_equal(1..2, 1..2)
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index 3f28d55ac1a..6b0bc4de5ee 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -1331,8 +1331,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
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index 5e6891a6a02..361d18dd4b4 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -676,6 +676,23 @@ class TestMarshal < Test::Unit::TestCase
assert_equal(['X', 'X'], Marshal.load(Marshal.dump(obj), ->(v) { v == str ? v.upcase : v }))
end
+ def test_marshal_proc_string_encoding
+ string = "foo"
+ payload = Marshal.dump(string)
+ Marshal.load(payload, ->(v) {
+ if v.is_a?(String)
+ assert_equal(string, v)
+ assert_equal(string.encoding, v.encoding)
+ end
+ v
+ })
+ end
+
+ def test_marshal_proc_freeze
+ object = { foo: [42, "bar"] }
+ assert_equal object, Marshal.load(Marshal.dump(object), :freeze.to_proc)
+ end
+
def test_marshal_load_extended_class_crash
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
begin;
@@ -789,8 +806,26 @@ class TestMarshal < Test::Unit::TestCase
def test_marshal_with_ruby2_keywords_hash
flagged_hash = ruby2_keywords_hash(key: 42)
- hash = Marshal.load(Marshal.dump(flagged_hash))
+ data = Marshal.dump(flagged_hash)
+ hash = Marshal.load(data)
assert_equal(42, ruby2_keywords_test(*[hash]))
+
+ hash2 = Marshal.load(data.sub(/\x06K(?=T\z)/, "\x08KEY"))
+ assert_raise(ArgumentError, /\(given 1, expected 0\)/) {
+ ruby2_keywords_test(*[hash2])
+ }
+ hash2 = Marshal.load(data.sub(/:\x06K(?=T\z)/, "I\\&\x06:\x0dencoding\"\x0aUTF-7"))
+ assert_raise(ArgumentError, /\(given 1, expected 0\)/) {
+ ruby2_keywords_test(*[hash2])
+ }
+ end
+
+ def test_invalid_byte_sequence_symbol
+ data = Marshal.dump(:K)
+ data = data.sub(/:\x06K/, "I\\&\x06:\x0dencoding\"\x0dUTF-16LE")
+ assert_raise(ArgumentError, /UTF-16LE: "\\x4B"/) {
+ Marshal.load(data)
+ }
end
def exception_test
@@ -823,4 +858,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_method.rb b/test/ruby/test_method.rb
index 0bd5dc63ddd..daf0ec73ca1 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -578,7 +578,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:mk8).parameters)
assert_equal([[:nokey]], method(:mnk).parameters)
# pending
- assert_equal([[:rest, :*], [:block, :&]], method(:mf).parameters)
+ assert_equal([[:rest, :*], [:keyrest, :**], [:block, :&]], method(:mf).parameters)
end
def test_unbound_parameters
@@ -604,7 +604,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], self.class.instance_method(:mk8).parameters)
assert_equal([[:nokey]], self.class.instance_method(:mnk).parameters)
# pending
- assert_equal([[:rest, :*], [:block, :&]], self.class.instance_method(:mf).parameters)
+ assert_equal([[:rest, :*], [:keyrest, :**], [:block, :&]], self.class.instance_method(:mf).parameters)
end
def test_bmethod_bound_parameters
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 2d7bdb47fc5..be23b84c462 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -404,19 +404,20 @@ class TestModule < Test::Unit::TestCase
assert_equal([:MIXIN, :USER], User.constants.sort)
end
- def test_self_initialize_copy
- bug9535 = '[ruby-dev:47989] [Bug #9535]'
- m = Module.new do
- def foo
- :ok
- end
- initialize_copy(self)
+ def test_initialize_copy
+ mod = Module.new { define_method(:foo) {:first} }
+ klass = Class.new { include mod }
+ instance = klass.new
+ assert_equal(:first, instance.foo)
+ new_mod = Module.new { define_method(:foo) { :second } }
+ assert_raise(TypeError) do
+ mod.send(:initialize_copy, new_mod)
end
- assert_equal(:ok, Object.new.extend(m).foo, bug9535)
+ 4.times { GC.start }
+ assert_equal(:first, instance.foo) # [BUG] unreachable
end
def test_initialize_copy_empty
- bug9813 = '[ruby-dev:48182] [Bug #9813]'
m = Module.new do
def x
end
@@ -426,12 +427,52 @@ class TestModule < Test::Unit::TestCase
assert_equal([:x], m.instance_methods)
assert_equal([:@x], m.instance_variables)
assert_equal([:X], m.constants)
- m.module_eval do
- initialize_copy(Module.new)
+ assert_raise(TypeError) do
+ m.module_eval do
+ initialize_copy(Module.new)
+ end
+ end
+
+ m = Class.new(Module) do
+ def initialize_copy(other)
+ # leave uninitialized
+ end
+ end.new.dup
+ c = Class.new
+ assert_operator(c.include(m), :<, m)
+ cp = Module.instance_method(:initialize_copy)
+ assert_raise(TypeError) do
+ cp.bind_call(m, Module.new)
+ end
+ end
+
+ class Bug18185 < Module
+ module InstanceMethods
+ end
+ attr_reader :ancestor_list
+ def initialize
+ @ancestor_list = ancestors
+ include InstanceMethods
+ end
+ class Foo
+ attr_reader :key
+ def initialize(key:)
+ @key = key
+ end
+ end
+ end
+
+ def test_module_subclass_initialize
+ mod = Bug18185.new
+ c = Class.new(Bug18185::Foo) do
+ include mod
end
- assert_empty(m.instance_methods, bug9813)
- assert_empty(m.instance_variables, bug9813)
- assert_empty(m.constants, bug9813)
+ anc = c.ancestors
+ assert_include(anc, mod)
+ assert_equal(1, anc.count(BasicObject), ->{anc.inspect})
+ b = c.new(key: 1)
+ assert_equal(1, b.key)
+ assert_not_include(mod.ancestor_list, BasicObject)
end
def test_dup
@@ -1047,6 +1088,7 @@ class TestModule < Test::Unit::TestCase
def test_attr_obsoleted_flag
c = Class.new do
extend Test::Unit::Assertions
+ extend Test::Unit::CoreAssertions
def initialize
@foo = :foo
@bar = :bar
diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb
index b5486d387c1..0593cb535d4 100644
--- a/test/ruby/test_numeric.rb
+++ b/test/ruby/test_numeric.rb
@@ -200,6 +200,14 @@ class TestNumeric < Test::Unit::TestCase
assert_nil(a <=> :foo)
end
+ def test_float_round_ndigits
+ bug14635 = "[ruby-core:86323]"
+ f = 0.5
+ 31.times do |i|
+ assert_equal(0.5, f.round(i+1), bug14635 + " (argument: #{i+1})")
+ end
+ end
+
def test_floor_ceil_round_truncate
a = Class.new(Numeric) do
def to_f; 1.5; end
diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb
index 7d4a773d4b8..24a190b2dfc 100644
--- a/test/ruby/test_objectspace.rb
+++ b/test/ruby/test_objectspace.rb
@@ -191,6 +191,8 @@ End
assert(false)
rescue my_error
end
+ ensure
+ GC.enable
end
def test_each_object
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index b0090d654a7..cbae6d5e8c3 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -150,6 +150,64 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_redefine_method('String', '-@', 'assert_nil(-"foo")')
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)')
+ 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)')
+ end
+
+ def test_trace_optimized_methods
+ bug14870 = "[ruby-core:87638]"
+ expected = [:-@, :max, :min, :+, :-, :*, :/, :%, :==, :<, :<=, :>, :>=, :<<,
+ :&, :|, :[], :[]=, :length, :empty?, :nil?, :succ, :!, :=~]
+ [:c_call, :c_return].each do |type|
+ methods = []
+ tp = TracePoint.new(type) { |tp| methods << tp.method_id }
+ tp.enable do
+ x = "a"; x = -x
+ [1].max
+ [1].min
+ x = 42 + 2
+ x = 42 - 2
+ x = 42 * 2
+ x = 42 / 2
+ x = 42 % 2
+ y = x == 42
+ y = x < 42
+ y = x <= 42
+ y = x > 42
+ y = x >= 42
+ x = x << 1
+ x = x & 1
+ x = x | 1
+ x = []; x[1]
+ x[1] = 2
+ x.length
+ x.empty?
+ x.nil?
+ x = 1; x.succ
+ !x
+ x = 'a'; x =~ /a/
+ x = y
+ end
+ assert_equal(expected, methods, bug14870)
+ end
+
+ methods = []
+ tp = TracePoint.new(:c_call, :c_return) { |tp| methods << tp.method_id }
+ tp.enable do
+ x = 1
+ x != 42
+ end
+ assert_equal([:!=, :==, :==, :!=], methods, bug14870)
+ end
+
def test_string_freeze_saves_memory
n = 16384
data = '.'.freeze
diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb
index 60edd001865..af45adb2b23 100644
--- a/test/ruby/test_pack.rb
+++ b/test/ruby/test_pack.rb
@@ -764,7 +764,7 @@ EXPECTED
$VERBOSE = true
- _, err = capture_io do
+ _, err = capture_output do
assert_equal "\000", [0].pack("*U")
end
@@ -783,7 +783,7 @@ EXPECTED
$VERBOSE = true
- _, err = capture_io do
+ _, err = capture_output do
assert_equal [0], "\000".unpack("*U")
end
@@ -869,4 +869,30 @@ 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
end
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index 625b6eb2234..3120016e60d 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -1162,6 +1162,10 @@ x = __ENCODING__
assert_syntax_error("def m\n\C-z""end", /unexpected/)
end
+ def test_unexpected_eof
+ assert_syntax_error('unless', /^ \^\Z/)
+ end
+
def test_location_of_invalid_token
assert_syntax_error('class xxx end', /^ \^~~\Z/)
end
@@ -1227,10 +1231,12 @@ 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"].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
end
def eval_separately(code)
diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb
index 2fdad78699c..35c41eb8b65 100644
--- a/test/ruby/test_pattern_matching.rb
+++ b/test/ruby/test_pattern_matching.rb
@@ -4,6 +4,25 @@ 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)
+ @original_formatter = DidYouMean.formatter
+ DidYouMean.formatter = NullFormatter.new
+ end
+ end
+
+ def teardown
+ if defined?(DidYouMean)
+ DidYouMean.formatter = @original_formatter
+ end
+ end
+
class C
class << self
attr_accessor :keys
@@ -1519,13 +1538,13 @@ END
assert_raise(NoMatchingPatternError) do
{a: 1} => {a: 0}
end
- assert_syntax_error("if {} => {a:}; end", /void value expression/)
- assert_syntax_error(%q{
- 1 => a, b
- }, /unexpected/, '[ruby-core:95098]')
- assert_syntax_error(%q{
- 1 => a:
- }, /unexpected/, '[ruby-core:95098]')
+
+ [1, 2] => a, b
+ assert_equal 1, a
+ assert_equal 2, b
+
+ {a: 1} => a:
+ assert_equal 1, a
assert_equal true, (1 in 1)
assert_equal false, (1 in 2)
@@ -1546,6 +1565,133 @@ END
def test_experimental_warning
assert_experimental_warning("case [0]; in [*, 0, *]; end")
end
+
+ ################################################################
+
+ def test_single_pattern_error_value_pattern
+ assert_raise_with_message(NoMatchingPatternError, "0: 1 === 0 does not return true") do
+ 0 => 1
+ end
+ end
+
+ def test_single_pattern_error_array_pattern
+ assert_raise_with_message(NoMatchingPatternError, "[]: Hash === [] does not return true") do
+ [] => Hash[]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct") do
+ 0 => []
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0]: [0] length mismatch (given 1, expected 0)") do
+ [0] => []
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[]: [] length mismatch (given 0, expected 1+)") do
+ [] => [_, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0, 0]: 1 === 0 does not return true") do
+ [0, 0] => [0, 1]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0, 0]: 1 === 0 does not return true") do
+ [0, 0] => [*, 0, 1]
+ end
+ end
+
+ def test_single_pattern_error_find_pattern
+ assert_raise_with_message(NoMatchingPatternError, "[]: Hash === [] does not return true") do
+ [] => Hash[*, _, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct") do
+ 0 => [*, _, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[]: [] length mismatch (given 0, expected 1+)") do
+ [] => [*, _, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0]: [0] does not match to find pattern") do
+ [0] => [*, 1, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0]: [0] does not match to find pattern") do
+ [0] => [*, {a:}, *]
+ raise a # suppress "unused variable: a" warning
+ end
+ end
+
+ def test_single_pattern_error_hash_pattern
+ assert_raise_with_message(NoMatchingPatternError, "{}: Array === {} does not return true") do
+ {} => Array[a:]
+ raise a # suppress "unused variable: a" warning
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct_keys") do
+ 0 => {a:}
+ raise a # suppress "unused variable: a" warning
+ end
+
+ assert_raise_with_message(NoMatchingPatternKeyError, "{:a=>0}: key not found: :aa") do
+ {a: 0} => {aa:}
+ raise aa # suppress "unused variable: aa" warning
+ rescue NoMatchingPatternKeyError => e
+ assert_equal({a: 0}, e.matchee)
+ assert_equal(:aa, e.key)
+ raise e
+ end
+
+ assert_raise_with_message(NoMatchingPatternKeyError, "{:a=>{:b=>0}}: key not found: :bb") do
+ {a: {b: 0}} => {a: {bb:}}
+ raise bb # suppress "unused variable: bb" warning
+ rescue NoMatchingPatternKeyError => e
+ assert_equal({b: 0}, e.matchee)
+ assert_equal(:bb, e.key)
+ raise e
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "{:a=>0}: 1 === 0 does not return true") do
+ {a: 0} => {a: 1}
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "{:a=>0}: {:a=>0} is not empty") do
+ {a: 0} => {}
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[{:a=>0}]: rest of {:a=>0} is not empty") do
+ [{a: 0}] => [{**nil}]
+ end
+ end
+
+ def test_single_pattern_error_as_pattern
+ assert_raise_with_message(NoMatchingPatternError, "[0]: 1 === 0 does not return true") do
+ case [0]
+ in [1] => _
+ end
+ end
+ end
+
+ def test_single_pattern_error_alternative_pattern
+ assert_raise_with_message(NoMatchingPatternError, "0: 2 === 0 does not return true") do
+ 0 => 1 | 2
+ end
+ end
+
+ def test_single_pattern_error_guard_clause
+ assert_raise_with_message(NoMatchingPatternError, "0: guard clause does not return true") do
+ case 0
+ in _ if false
+ end
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "0: guard clause does not return true") do
+ case 0
+ in _ unless true
+ end
+ end
+ end
end
END_of_GUARD
Warning[:experimental] = experimental
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index 80d2eefca9b..636871f8223 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -261,6 +261,18 @@ class TestProcess < Test::Unit::TestCase
}
end
+ def test_overwrite_ENV
+ assert_separately([],"#{<<~"begin;"}\n#{<<~"end;"}")
+ BUG = "[ruby-core:105223] [Bug #18164]"
+ begin;
+ $VERBOSE = nil
+ ENV = {}
+ pid = spawn({}, *#{TRUECOMMAND.inspect})
+ ENV.replace({})
+ assert_kind_of(Integer, pid, BUG)
+ end;
+ end
+
MANDATORY_ENVS = %w[RUBYLIB MJIT_SEARCH_BUILD_DIR]
case RbConfig::CONFIG['target_os']
when /linux/
@@ -1720,6 +1732,9 @@ class TestProcess < Test::Unit::TestCase
end
def test_no_curdir
+ if /solaris/i =~ RUBY_PLATFORM
+ skip "Temporary skip to avoid CI failures after commit to use realpath on required files"
+ end
with_tmpchdir {|d|
Dir.mkdir("vd")
status = nil
@@ -2530,4 +2545,96 @@ 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_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)
end
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index 14c112f344c..19857b035c0 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 Minitest::Unit.current_repeat_count > 0
+ skip 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 Minitest::Unit.current_repeat_count > 0
+ skip if Test::Unit::Runner.current_repeat_count > 0
foo = Foo.new
assert_raise(NameError) { Foo.instance_method(:z) }
@@ -747,6 +747,13 @@ class TestRefinement < Test::Unit::TestCase
end
end
+ def self.suppress_verbose
+ verbose, $VERBOSE = $VERBOSE, nil
+ yield
+ ensure
+ $VERBOSE = verbose
+ end
+
module IncludeIntoRefinement
class C
def bar
@@ -774,7 +781,9 @@ class TestRefinement < Test::Unit::TestCase
module M
refine C do
- include Mixin
+ TestRefinement.suppress_verbose do
+ include Mixin
+ end
def baz
return super << " M#baz"
@@ -837,7 +846,9 @@ class TestRefinement < Test::Unit::TestCase
module M
refine C do
- prepend Mixin
+ TestRefinement.suppress_verbose do
+ prepend Mixin
+ end
def baz
return super << " M#baz"
@@ -2537,6 +2548,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
@@ -2559,6 +2589,89 @@ class TestRefinement < Test::Unit::TestCase
assert_equal(:refined, Bug17822::Client.call_foo)
end
+ def test_ancestors
+ refinement = nil
+ as = nil
+ Module.new do
+ refine Array do
+ refinement = self
+ as = ancestors
+ end
+ end
+ 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 D
+ refine A do
+ TestRefinement.suppress_verbose do
+ include B
+ end
+
+ def foo
+ "refined"
+ end
+ end
+ end
+
+ module UsingC
+ using C
+
+ def self.call_bar
+ A.new.bar
+ end
+ end
+
+ module UsingD
+ using D
+
+ def self.call_bar
+ A.new.bar
+ end
+ end
+ end
+
+ def test_import_methods
+ assert_equal("refined:bar", TestImport::UsingC.call_bar)
+ assert_equal("original:bar", TestImport::UsingD.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
+
private
def eval_using(mod, s)
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 5ba50b35171..2bf4649f144 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -265,6 +265,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)
@@ -473,6 +494,40 @@ class TestRegexp < Test::Unit::TestCase
assert_equal("foobarbaz", m.string)
end
+ def test_match_matchsubstring
+ m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+ assert_equal("HX1138", m.match(0))
+ assert_equal("8", m.match(4))
+ assert_nil(m.match(5))
+
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+ assert_equal("\u3043", m.match(1))
+ assert_nil(m.match(2))
+ assert_equal("\u3044", m.match(3))
+
+ m = /(?<foo>.)(?<n>[^aeiou])?(?<bar>.+)/.match("hoge\u3042")
+ assert_equal("h", m.match(:foo))
+ assert_nil(m.match(:n))
+ assert_equal("oge\u3042", m.match(:bar))
+ end
+
+ def test_match_match_length
+ m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+ assert_equal(6, m.match_length(0))
+ assert_equal(1, m.match_length(4))
+ assert_nil(m.match_length(5))
+
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+ assert_equal(1, m.match_length(1))
+ assert_nil(m.match_length(2))
+ assert_equal(1, m.match_length(3))
+
+ m = /(?<foo>.)(?<n>[^aeiou])?(?<bar>.+)/.match("hoge\u3042")
+ assert_equal(1, m.match_length(:foo))
+ assert_nil(m.match_length(:n))
+ assert_equal(4, m.match_length(:bar))
+ end
+
def test_match_inspect
m = /(...)(...)(...)(...)?/.match("foobarbaz")
assert_equal('#<MatchData "foobarbaz" 1:"foo" 2:"bar" 3:"baz" 4:nil>', m.inspect)
@@ -712,11 +767,16 @@ class TestRegexp < Test::Unit::TestCase
test = proc {|&blk| "abc".sub("a", ""); blk.call($~) }
bug10877 = '[ruby-core:68209] [Bug #10877]'
+ bug18160 = '[Bug #18160]'
test.call {|m| assert_raise_with_message(IndexError, /foo/, bug10877) {m["foo"]} }
key = "\u{3042}"
[Encoding::UTF_8, Encoding::Shift_JIS, Encoding::EUC_JP].each do |enc|
idx = key.encode(enc)
- test.call {|m| assert_raise_with_message(IndexError, /#{idx}/, bug10877) {m[idx]} }
+ pat = /#{idx}/
+ test.call {|m| assert_raise_with_message(IndexError, pat, bug10877) {m[idx]} }
+ test.call {|m| assert_raise_with_message(IndexError, pat, bug18160) {m.offset(idx)} }
+ test.call {|m| assert_raise_with_message(IndexError, pat, bug18160) {m.begin(idx)} }
+ test.call {|m| assert_raise_with_message(IndexError, pat, bug18160) {m.end(idx)} }
end
test.call {|m| assert_equal(/a/, m.regexp) }
test.call {|m| assert_equal("abc", m.string) }
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index 4ef08f8b488..7a9faf18f9a 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -434,6 +434,32 @@ class TestRequire < Test::Unit::TestCase
}
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
+ skip "File.symlink is not implemented"
+ end
+ }
+ }
+ end
+
def test_frozen_loaded_features
bug3756 = '[ruby-core:31913]'
assert_in_out_err(['-e', '$LOADED_FEATURES.freeze; require "ostruct"'], "",
@@ -531,6 +557,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|
@@ -711,8 +759,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
@@ -839,6 +887,23 @@ class TestRequire < Test::Unit::TestCase
}
end
+ def test_provide_in_required_file
+ paths, loaded = $:.dup, $".dup
+ Dir.mktmpdir do |tmp|
+ provide = File.realdirpath("provide.rb", tmp)
+ File.write(File.join(tmp, "target.rb"), "raise __FILE__\n")
+ File.write(provide, '$" << '"'target.rb'\n")
+ $:.replace([tmp])
+ assert(require("provide"))
+ assert(!require("target"))
+ assert_equal($".pop, provide)
+ assert_equal($".pop, "target.rb")
+ end
+ ensure
+ $:.replace(paths)
+ $".replace(loaded)
+ end
+
if defined?($LOAD_PATH.resolve_feature_path)
def test_resolve_feature_path
paths, loaded = $:.dup, $".dup
diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb
index e26a24e8ada..579d0cb3624 100644
--- a/test/ruby/test_rubyoptions.rb
+++ b/test/ruby/test_rubyoptions.rb
@@ -10,6 +10,8 @@ class TestRubyOptions < Test::Unit::TestCase
NO_JIT_DESCRIPTION =
if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # checking -DMJIT_FORCE_ENABLE
RUBY_DESCRIPTION.sub(/\+JIT /, '')
+ elsif defined?(YJIT.enabled?) && YJIT.enabled? # checking -DYJIT_FORCE_ENABLE
+ RUBY_DESCRIPTION.sub(/\+YJIT /, '')
else
RUBY_DESCRIPTION
end
@@ -140,10 +142,12 @@ class TestRubyOptions < Test::Unit::TestCase
private_constant :VERSION_PATTERN_WITH_JIT
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
assert_equal(NO_JIT_DESCRIPTION, r[0])
+ elsif defined?(YJIT.enabled?) && YJIT.enabled? && !yjit_force_enabled? # checking -DYJIT_FORCE_ENABLE
+ assert_equal(NO_JIT_DESCRIPTION, r[0])
else
assert_equal(RUBY_DESCRIPTION, r[0])
end
@@ -203,9 +207,12 @@ 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 defined?(RubyVM::JIT) && RubyVM::JIT.enabled? || defined?(YJIT.enabled?) && 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])
@@ -214,13 +221,14 @@ class TestRubyOptions < Test::Unit::TestCase
end
return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no'
+ return if yjit_force_enabled?
[
%w(--version --jit --disable=jit),
%w(--version --enable=jit --disable=jit),
%w(--version --enable-jit --disable-jit),
].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)
@@ -233,12 +241,12 @@ class TestRubyOptions < Test::Unit::TestCase
%w(--version --enable=jit),
%w(--version --enable-jit),
].each do |args|
- assert_in_out_err(args) do |r, e|
+ assert_in_out_err([env] + 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])
+ assert_equal(EnvUtil.invoke_ruby([env, '--jit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
end
assert_equal([], e)
end
@@ -1103,7 +1111,7 @@ class TestRubyOptions < Test::Unit::TestCase
# 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/)
+ assert_in_out_err([env, "--disable-yjit", "--jit-debug=-O0 -O1", "--jit-verbose=2", "" ], "", [], /-O0 -O1/)
end
end
@@ -1112,4 +1120,8 @@ class TestRubyOptions < Test::Unit::TestCase
def mjit_force_enabled?
"#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?MJIT_FORCE_ENABLE\b/)
end
+
+ def yjit_force_enabled?
+ "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?YJIT_FORCE_ENABLE\b/)
+ end
end
diff --git a/test/ruby/test_rubyvm.rb b/test/ruby/test_rubyvm.rb
index 67d46e27adb..7d4588a165c 100644
--- a/test/ruby/test_rubyvm.rb
+++ b/test/ruby/test_rubyvm.rb
@@ -15,4 +15,57 @@ class TestRubyVM < Test::Unit::TestCase
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
+ 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_settracefunc.rb b/test/ruby/test_settracefunc.rb
index dafe58d70ce..c6955467c47 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -564,6 +564,16 @@ class TestSetTraceFunc < Test::Unit::TestCase
}
end
+ # Bug #18264
+ def test_tracpoint_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 trace_by_set_trace_func
events = []
trace = nil
@@ -831,6 +841,56 @@ class TestSetTraceFunc < Test::Unit::TestCase
}
end
+ def test_tracepoint_attr
+ c = Class.new do
+ attr_accessor :x
+ 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
@@ -982,20 +1042,24 @@ class TestSetTraceFunc < Test::Unit::TestCase
def test_tracepoint_with_multithreads
assert_nothing_raised do
- TracePoint.new{
+ TracePoint.new(:line){
10.times{
Thread.pass
}
}.enable do
(1..10).map{
Thread.new{
- 1000.times{
+ 1_000.times{|i|
+ _a = i
}
}
}.each{|th|
th.join
}
end
+ _a = 1
+ _b = 2
+ _c = 3 # to make sure the deletion of unused TracePoints
end
end
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index e1a957eebfc..3f7c06e0756 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -105,6 +105,16 @@ PREP
CODE
end
+ # Bug #18154
+ def test_initialize_nofree_memory_leak
+ assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
+code = proc {0.to_s.__send__(:initialize, capacity: 10000)}
+1_000.times(&code)
+PREP
+100_000.times(&code)
+CODE
+ end
+
def test_AREF # '[]'
assert_equal("A", S("AooBar")[0])
assert_equal("B", S("FooBaB")[-1])
@@ -1170,6 +1180,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}
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 31db1320fc7..fc40a7f21a9 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -200,17 +200,29 @@ 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("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)})")}
+ 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)
end
def test_keyword_empty_splat
@@ -1061,19 +1073,19 @@ 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_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
+ 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
@@ -1638,7 +1650,8 @@ eom
assert_equal(-1, obj.method(:foo).arity)
parameters = obj.method(:foo).parameters
assert_equal(:rest, parameters.dig(0, 0))
- assert_equal(:block, parameters.dig(1, 0))
+ assert_equal(:keyrest, parameters.dig(1, 0))
+ assert_equal(:block, parameters.dig(2, 0))
end
end
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index 19a3529005c..7b37aeb202e 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -235,6 +235,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
diff --git a/test/ruby/test_thread_cv.rb b/test/ruby/test_thread_cv.rb
index 812c4221bcd..88733419da1 100644
--- a/test/ruby/test_thread_cv.rb
+++ b/test/ruby/test_thread_cv.rb
@@ -89,6 +89,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_time.rb b/test/ruby/test_time.rb
index 99f2e8048d7..85667e2d1fb 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -39,6 +39,7 @@ class TestTime < Test::Unit::TestCase
def test_new
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]'
@@ -110,7 +111,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 Minitest::Unit.current_repeat_count > 0
+ skip 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)
@@ -1168,7 +1169,7 @@ class TestTime < Test::Unit::TestCase
def test_2038
# Giveup to try 2nd test because some state is changed.
- skip if Minitest::Unit.current_repeat_count > 0
+ skip 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)
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
new file mode 100644
index 00000000000..9014a1e5673
--- /dev/null
+++ b/test/ruby/test_yjit.rb
@@ -0,0 +1,634 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'envutil'
+require 'tmpdir'
+
+return unless defined?(YJIT) && YJIT.enabled?
+
+# Tests for YJIT with assertions on compilation and side exits
+# insipired by the MJIT tests in test/ruby/test_jit.rb
+class TestYJIT < Test::Unit::TestCase
+ def test_yjit_in_ruby_description
+ assert_includes(RUBY_DESCRIPTION, '+YJIT')
+ end
+
+ 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),
+ ].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
+
+ 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/)
+ assert_in_out_err('--yjit-greedy-versioning=1', '', [], /warning: argument to --yjit-greedy-versioning is ignored/)
+ end
+
+ def test_yjit_stats_and_v_no_error
+ _stdout, stderr, _status = EnvUtil.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 YJIT.enabled?'], '', ['true'])
+ 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_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])
+ assert_compiles('{}[:foo] = :bar', insns: %i[opt_aset])
+ assert_compiles('[1,2,3][0..-1] = []', insns: %i[opt_aset])
+ assert_compiles('"foo"[3] = "d"', insns: %i[opt_aset])
+ 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_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_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_opt_getinlinecache
+ assert_compiles(<<~RUBY, insns: %i[opt_getinlinecache], result: 123, min_calls: 2)
+ def get_foo
+ FOO
+ end
+
+ FOO = 123
+
+ get_foo # warm inline cache
+ get_foo
+ RUBY
+ end
+
+ def test_opt_getinlinecache_slowpath
+ assert_compiles(<<~RUBY, exits: { opt_getinlinecache: 1 }, result: [42, 42, 1, 1], min_calls: 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_string_interpolation
+ assert_compiles(<<~'RUBY', insns: %i[checktype concatstrings], result: "foobar", min_calls: 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[checktype concatstrings tostring], result: "123")
+ def make_str(foo, bar)
+ "#{foo}#{bar}"
+ end
+
+ make_str(1, 23)
+ RUBY
+ end
+
+ def test_invokebuiltin
+ 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_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_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], min_calls: 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_ctx_different_mappings
+ # regression test simplified from URI::Generic#hostname=
+ 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 = YJIT.runtime_stats
+ return :ok unless stats[:all_stats]
+ return :ok if stats[:invalidation_count] < 10
+
+ :fail
+ RUBY
+ end
+
+ def assert_no_exits(script)
+ assert_compiles(script)
+ end
+
+ ANY = Object.new
+ def assert_compiles(test_script, insns: [], min_calls: 1, stdout: nil, exits: {}, result: ANY, frozen_string_literal: nil)
+ reset_stats = <<~RUBY
+ YJIT.runtime_stats
+ YJIT.reset_stats!
+ RUBY
+
+ write_results = <<~RUBY
+ stats = YJIT.runtime_stats
+
+ def collect_blocks(blocks)
+ blocks.sort_by(&:address).map { |b| [b.iseq_start_index, b.iseq_end_index] }
+ end
+
+ def collect_iseqs(iseq)
+ iseq_array = iseq.to_a
+ insns = iseq_array.last.grep(Array)
+ blocks = YJIT.blocks_for(iseq)
+ h = {
+ name: iseq_array[5],
+ insns: insns,
+ blocks: collect_blocks(blocks),
+ }
+ arr = [h]
+ iseq.each_child { |c| arr.concat collect_iseqs(c) }
+ arr
+ end
+
+ iseq = RubyVM::InstructionSequence.of(_test_proc)
+ IO.open(3).write Marshal.dump({
+ result: #{result == ANY ? "nil" : "result"},
+ stats: stats,
+ iseqs: collect_iseqs(iseq),
+ disasm: iseq.disasm
+ })
+ RUBY
+
+ script = <<~RUBY
+ #{"# frozen_string_literal: true" if frozen_string_literal}
+ _test_proc = -> {
+ #{test_script}
+ }
+ #{reset_stats}
+ result = _test_proc.call
+ #{write_results}
+ RUBY
+
+ status, out, err, stats = eval_with_jit(script, min_calls: min_calls)
+
+ 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]
+ iseqs = stats[:iseqs]
+ disasm = stats[:disasm]
+
+ # Only available when RUBY_DEBUG enabled
+ 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 }
+ if exits != :any && exits != recorded_exits
+ flunk "Expected #{exits.empty? ? "no" : exits.inspect} exits" \
+ ", but got\n#{recorded_exits.inspect}"
+ end
+ end
+
+ # Only available when RUBY_DEBUG enabled
+ if runtime_stats[:all_stats]
+ missed_insns = insns.dup
+ all_compiled_blocks = {}
+ iseqs.each do |iseq|
+ compiled_blocks = iseq[:blocks].map { |from, to| (from...to) }
+ all_compiled_blocks[iseq[:name]] = compiled_blocks
+ compiled_insns = iseq[:insns]
+ next_idx = 0
+ compiled_insns.map! do |insn|
+ # TODO: not sure this is accurate for determining insn size
+ idx = next_idx
+ next_idx += insn.length
+ [idx, *insn]
+ end
+
+ compiled_insns.each do |idx, op, *arguments|
+ next unless missed_insns.include?(op)
+ next unless compiled_blocks.any? { |block| block === idx }
+
+ # 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.\nCompiled ranges: #{all_compiled_blocks.inspect}\niseq:\n#{disasm}"
+ end
+ end
+ end
+
+ def eval_with_jit(script, min_calls: 1, timeout: 1000)
+ args = [
+ "--disable-gems",
+ "--yjit-call-threshold=#{min_calls}",
+ "--yjit-stats"
+ ]
+ args << "-e" << script
+ stats_r, stats_w = IO.pipe
+ out, err, status = EnvUtil.invoke_ruby(args,
+ '', true, true, timeout: timeout, ios: {3 => stats_w}
+ )
+ stats_w.close
+ stats = stats_r.read
+ stats = Marshal.load(stats) if !stats.empty?
+ stats_r.close
+ [status, out, err, stats]
+ end
+end
diff --git a/test/rubygems/bogussources.rb b/test/rubygems/bogussources.rb
deleted file mode 100644
index 4f783c3bd2b..00000000000
--- a/test/rubygems/bogussources.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-#--
-# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
-# All rights reserved.
-# See LICENSE.txt for permissions.
-#++
-
-require 'rubygems'
-Gem.use_paths("test/mock/gems")
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index 36be6a25b7f..504e25ea52e 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -396,6 +396,7 @@ class Gem::TestCase < Test::Unit::TestCase
ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = PRIVATE_KEY_PASSPHRASE
+ Gem.instance_variable_set(:@default_specifications_dir, nil)
if Gem.java_platform?
@orig_default_gem_home = RbConfig::CONFIG['default_gem_home']
RbConfig::CONFIG['default_gem_home'] = @gemhome
@@ -479,6 +480,7 @@ class Gem::TestCase < Test::Unit::TestCase
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
else
@@ -595,7 +597,7 @@ class Gem::TestCase < Test::Unit::TestCase
def have_git?
return if in_path? @git
- skip '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:
@@ -823,16 +825,6 @@ 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)
spec = util_spec name, version, deps
@@ -1295,7 +1287,11 @@ Also, a list:
end
def ruby_with_rubygems_in_load_path
- [Gem.ruby, "-I", $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) }]
+ [Gem.ruby, "-I", rubygems_path]
+ end
+
+ def rubygems_path
+ $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) }
end
def with_clean_path_to_ruby
@@ -1523,14 +1519,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
##
diff --git a/test/rubygems/private_ec_key.pem b/test/rubygems/private_ec_key.pem
new file mode 100644
index 00000000000..5d855d0dfc8
--- /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/test_gem.rb b/test/rubygems/test_gem.rb
index 79ea89e2fa6..3c95982d4be 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -19,79 +19,72 @@ class TestGem < Gem::TestCase
common_installer_setup
- ENV.delete 'RUBYGEMS_GEMDEPS'
@additional = %w[a b].map {|d| File.join @tempdir, d }
util_remove_interrupt_command
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
@@ -211,25 +204,21 @@ class TestGem < Gem::TestCase
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
@@ -540,7 +529,6 @@ class TestGem < Gem::TestCase
s.executables = []
end
install_specs spec
- # Should not find a-10's non-abin (bug)
assert_equal @abin_path, Gem.bin_path('a', 'abin')
end
@@ -664,22 +652,22 @@ class TestGem < Gem::TestCase
end
def test_self_use_gemdeps
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
+ with_rubygems_gemdeps('-') do
+ FileUtils.mkdir_p 'detect/a/b'
+ FileUtils.mkdir_p 'detect/a/Isolate'
- FileUtils.mkdir_p 'detect/a/b'
- FileUtils.mkdir_p 'detect/a/Isolate'
+ FileUtils.touch 'detect/Isolate'
- FileUtils.touch 'detect/Isolate'
+ begin
+ Dir.chdir 'detect/a/b'
- begin
- Dir.chdir 'detect/a/b'
+ Gem.use_gemdeps
- assert_equal add_bundler_full_name([]), Gem.use_gemdeps.map(&:full_name)
- ensure
- Dir.chdir @tempdir
+ assert_equal add_bundler_full_name([]), loaded_spec_names
+ ensure
+ Dir.chdir @tempdir
+ end
end
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end
def test_self_dir
@@ -933,56 +921,17 @@ class TestGem < Gem::TestCase
assert_equal true, Gem.loaded_specs.keys.include?('foo')
end
- def util_path
- ENV.delete "GEM_HOME"
- ENV.delete "GEM_PATH"
- end
-
def test_self_path
assert_equal [Gem.dir], Gem.path
end
def test_self_path_default
- util_path
-
- if defined?(APPLE_GEM_HOME)
- orig_APPLE_GEM_HOME = APPLE_GEM_HOME
- Object.send :remove_const, :APPLE_GEM_HOME
- end
+ ENV.delete "GEM_HOME"
+ ENV.delete "GEM_PATH"
Gem.instance_variable_set :@paths, nil
assert_equal [Gem.default_path, Gem.dir].flatten.uniq, Gem.path
- ensure
- Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME if orig_APPLE_GEM_HOME
- end
-
- unless win_platform?
- def test_self_path_APPLE_GEM_HOME
- util_path
-
- Gem.clear_paths
- apple_gem_home = File.join @tempdir, 'apple_gem_home'
-
- old, $-w = $-w, nil
- Object.const_set :APPLE_GEM_HOME, apple_gem_home
- $-w = old
-
- assert_includes Gem.path, apple_gem_home
- ensure
- Object.send :remove_const, :APPLE_GEM_HOME
- end
-
- def test_self_path_APPLE_GEM_HOME_GEM_PATH
- Gem.clear_paths
- ENV['GEM_PATH'] = @gemhome
- apple_gem_home = File.join @tempdir, 'apple_gem_home'
- Gem.const_set :APPLE_GEM_HOME, apple_gem_home
-
- refute Gem.path.include?(apple_gem_home)
- ensure
- Gem.send :remove_const, :APPLE_GEM_HOME
- end
end
def test_self_path_ENV_PATH
@@ -1485,24 +1434,22 @@ class TestGem < Gem::TestCase
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
@@ -1580,6 +1527,31 @@ class TestGem < Gem::TestCase
assert_equal %w[plugin], PLUGINS_LOADED
end
+ def test_load_user_installed_plugins
+ plugin_path = File.join "lib", "rubygems_plugin.rb"
+
+ Dir.chdir @tempdir do
+ 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|
+ s.files << plugin_path
+ end
+
+ install_gem_user foo
+ end
+
+ Gem.paths = { "GEM_PATH" => [Gem.dir, Gem.user_dir].join(File::PATH_SEPARATOR) }
+
+ gem 'foo'
+
+ Gem.load_plugins
+
+ assert_equal %w[plugin], PLUGINS_LOADED
+ end
+
def test_load_env_plugins
with_plugin('load') { Gem.load_env_plugins }
assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil
@@ -1689,11 +1661,11 @@ class TestGem < Gem::TestCase
f.puts "gem 'c'"
end
- ENV['RUBYGEMS_GEMDEPS'] = path
+ with_rubygems_gemdeps(path) do
+ Gem.use_gemdeps
- Gem.use_gemdeps
-
- assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names
+ 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
@@ -1711,10 +1683,13 @@ class TestGem < Gem::TestCase
f.puts "gem 'c'"
end
- ENV['RUBYGEMS_GEMDEPS'] = "-"
+ with_rubygems_gemdeps("-") do
+ expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name)
+
+ Gem.use_gemdeps
- expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact
- assert_equal expected_specs, Gem.use_gemdeps.sort_by {|s| s.name }
+ 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")) }
@@ -1726,10 +1701,18 @@ class TestGem < Gem::TestCase
names
end
- def test_looks_for_gemdeps_files_automatically_on_start
+ def test_looks_for_gemdeps_files_automatically_from_binstubs
pend "Requiring bundler messes things up" if Gem.java_platform?
- a = util_spec "a", "1", nil, "lib/a.rb"
+ 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"
@@ -1741,31 +1724,44 @@ class TestGem < Gem::TestCase
install_gem c, :install_dir => path
ENV['GEM_PATH'] = path
- ENV['RUBYGEMS_GEMDEPS'] = "-"
- path = File.join @tempdir, "gem.deps.rb"
- cmd = [*ruby_with_rubygems_in_load_path,
- "-I#{BUNDLER_LIB_PATH}"]
- cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort"
+ 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}"
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- end
- out0 = IO.popen(cmd, &:read).split(/\n/)
+ path = File.join @tempdir, "gem.deps.rb"
- File.open path, "a" do |f|
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
- out = IO.popen(cmd, &:read).split(/\n/)
+ 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
+ assert_equal ["b-1", "c-1"], out - out0
+ end
end
- def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir
+ 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", nil, "lib/a.rb"
+ 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"
@@ -1777,29 +1773,34 @@ class TestGem < Gem::TestCase
install_gem c, :install_dir => path
ENV['GEM_PATH'] = path
- ENV['RUBYGEMS_GEMDEPS'] = "-"
- Dir.mkdir "sub1"
+ with_rubygems_gemdeps("-") do
+ Dir.mkdir "sub1"
- path = File.join @tempdir, "gem.deps.rb"
- cmd = [*ruby_with_rubygems_in_load_path, "-Csub1",
- "-I#{BUNDLER_LIB_PATH}"]
- cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort"
+ new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}"
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- end
- out0 = IO.popen(cmd, &:read).split(/\n/)
+ path = File.join @tempdir, "gem.deps.rb"
- File.open path, "a" do |f|
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
- out = IO.popen(cmd, &:read).split(/\n/)
+ 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"
+ Dir.rmdir "sub1"
- assert_equal ["b-1", "c-1"], out - out0
+ assert_equal ["b-1", "c-1"], out - out0
+ end
end
def test_register_default_spec
@@ -1863,21 +1864,19 @@ class TestGem < Gem::TestCase
end
def test_use_gemdeps_ENV
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
-
- spec = util_spec 'a', 1
+ with_rubygems_gemdeps(nil) do
+ spec = util_spec 'a', 1
- refute spec.activated?
+ refute spec.activated?
- File.open 'gem.deps.rb', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'gem.deps.rb', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- refute spec.activated?
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ refute spec.activated?
+ end
end
def test_use_gemdeps_argument_missing
@@ -1890,110 +1889,96 @@ class TestGem < Gem::TestCase
end
def test_use_gemdeps_argument_missing_match_ENV
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] =
- ENV['RUBYGEMS_GEMDEPS'], 'gem.deps.rb'
+ with_rubygems_gemdeps('gem.deps.rb') do
+ e = assert_raise ArgumentError do
+ Gem.use_gemdeps 'gem.deps.rb'
+ end
- e = assert_raise ArgumentError do
- Gem.use_gemdeps 'gem.deps.rb'
+ assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
+ e.message
end
-
- assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
- e.message
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end
def test_use_gemdeps_automatic
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
-
- spec = util_spec 'a', 1
- install_specs spec
- spec = Gem::Specification.find {|s| s == spec }
+ with_rubygems_gemdeps('-') do
+ spec = util_spec 'a', 1
+ install_specs spec
+ spec = Gem::Specification.find {|s| s == spec }
- refute spec.activated?
+ refute spec.activated?
- File.open 'Gemfile', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'Gemfile', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
+ end
end
def test_use_gemdeps_automatic_missing
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
-
- Gem.use_gemdeps
+ with_rubygems_gemdeps('-') do
+ Gem.use_gemdeps
- assert true # count
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ assert true # count
+ end
end
def test_use_gemdeps_disabled
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], ''
+ with_rubygems_gemdeps('') do
+ spec = util_spec 'a', 1
- spec = util_spec 'a', 1
-
- refute spec.activated?
+ refute spec.activated?
- File.open 'gem.deps.rb', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'gem.deps.rb', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- refute spec.activated?
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ refute spec.activated?
+ end
end
def test_use_gemdeps_missing_gem
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
-
- File.open 'x', 'w' do |io|
- io.write 'gem "a"'
- end
+ with_rubygems_gemdeps('x') do
+ File.open 'x', 'w' do |io|
+ io.write 'gem "a"'
+ end
- expected = <<-EXPECTED
+ expected = <<-EXPECTED
Could not find gem 'a' in locally installed gems.
-The source does not contain any versions of 'a'
-You may need to `gem install -g` to install missing gems
+You may need to `bundle install` to install missing gems
- EXPECTED
+ EXPECTED
- Gem::Deprecate.skip_during do
- actual_stdout, actual_stderr = capture_output do
- Gem.use_gemdeps
+ 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
- assert_empty actual_stdout
- assert_equal(expected, actual_stderr)
end
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end
def test_use_gemdeps_specific
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
+ with_rubygems_gemdeps('x') do
+ spec = util_spec 'a', 1
+ install_specs spec
- spec = util_spec 'a', 1
- install_specs spec
-
- spec = Gem::Specification.find {|s| s == spec }
- refute spec.activated?
+ spec = Gem::Specification.find {|s| s == spec }
+ refute spec.activated?
- File.open 'x', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'x', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
+ end
end
def test_operating_system_defaults
@@ -2111,4 +2096,22 @@ You may need to `gem install -g` 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_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb
index f722678a192..077be11d55e 100644
--- a/test/rubygems/test_gem_commands_cert_command.rb
+++ b/test/rubygems/test_gem_commands_cert_command.rb
@@ -14,9 +14,10 @@ class TestGemCommandsCertCommand < Gem::TestCase
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'
@@ -142,6 +143,42 @@ Added '/CN=alternate/DC=example'
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'
email = "nobody@"
@@ -279,6 +316,28 @@ Added '/CN=alternate/DC=example'
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_not_exist File.join(@tempdir, 'gem-private_key.pem')
+ end
+
def test_execute_certificate
use_ui @ui do
@cmd.handle_options %W[--certificate #{PUBLIC_CERT_FILE}]
@@ -742,7 +801,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
@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
diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb
index 48ac040d0e1..535180983b1 100644
--- a/test/rubygems/test_gem_commands_install_command.rb
+++ b/test/rubygems/test_gem_commands_install_command.rb
@@ -1067,6 +1067,31 @@ ERROR: Possible alternatives: non_existent_with_hint
assert_equal x, e
end
+ def test_redact_credentials_from_uri_on_warning
+ spec_fetcher do |fetcher|
+ fetcher.download 'a', 2
+ end
+
+ Gem.sources << "http://username:SECURE_TOKEN@nonexistent.example"
+
+ @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-2], @cmd.installed_specs.map {|spec| spec.full_name }
+
+ assert_match "1 gem installed", @ui.output
+
+ e = @ui.error
+
+ x = "WARNING: Unable to pull data from 'http://username:REDACTED@nonexistent.example': no data for http://username:REDACTED@nonexistent.example/specs.4.8.gz (http://username:REDACTED@nonexistent.example/specs.4.8.gz)\n"
+ assert_equal x, e
+ end
+
def test_execute_uses_from_a_gemdeps
spec_fetcher do |fetcher|
fetcher.gem 'a', 2
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index a2b390d6393..988f14146d7 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -33,6 +33,8 @@ class TestGemInstaller < Gem::InstallerTestCase
require 'rubygems'
+Gem.use_gemdeps
+
version = \">= 0.a\"
str = ARGV.first
diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb
index 3fa2c1911c4..48dcbee9f1f 100644
--- a/test/rubygems/test_gem_package.rb
+++ b/test/rubygems/test_gem_package.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require_relative 'package/tar_test_case'
-require 'digest'
+require 'rubygems/openssl'
class TestGemPackage < Gem::Package::TarTestCase
def setup
@@ -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),
+ 'data.tar.gz' => OpenSSL::Digest::SHA512.hexdigest(tar),
},
'SHA256' => {
'metadata.gz' => metadata_sha256,
- 'data.tar.gz' => Digest::SHA256.hexdigest(tar),
+ 'data.tar.gz' => OpenSSL::Digest::SHA256.hexdigest(tar),
},
}
@@ -574,18 +574,19 @@ class TestGemPackage < Gem::Package::TarTestCase
destination_subdir = File.join @destination, 'subdir'
FileUtils.mkdir_p destination_subdir
- e = assert_raise(Gem::Package::PathError, Errno::EACCES) do
+ expected_exceptions = 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
@@ -608,20 +609,20 @@ class TestGemPackage < Gem::Package::TarTestCase
tar.add_symlink 'link/dir', '.', 16877
end
- e = assert_raise(Gem::Package::PathError, Errno::EACCES) do
+ expected_exceptions = 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
@@ -856,7 +857,7 @@ class TestGemPackage < Gem::Package::TarTestCase
io.write metadata_gz
end
- digest = Digest::SHA1.new
+ digest = OpenSSL::Digest::SHA1.new
digest << metadata_gz
checksums = {
@@ -1015,7 +1016,7 @@ class TestGemPackage < Gem::Package::TarTestCase
bogus_data = Gem::Util.gzip 'hello'
fake_signer = Class.new do
def digest_name; 'SHA512'; end
- def digest_algorithm; Digest(:SHA512).new; end
+ def digest_algorithm; OpenSSL::Digest(:SHA512).new; end
def key; 'key'; end
def sign(*); 'fake_sig'; end
end
diff --git a/test/rubygems/test_gem_path_support.rb b/test/rubygems/test_gem_path_support.rb
index 88a3cc29b96..394cba2b7f2 100644
--- a/test/rubygems/test_gem_path_support.rb
+++ b/test/rubygems/test_gem_path_support.rb
@@ -16,7 +16,7 @@ class TestGemPathSupport < Gem::TestCase
assert_equal ENV["GEM_HOME"], ps.home
- expected = util_path
+ expected = ENV["GEM_PATH"].split(File::PATH_SEPARATOR)
assert_equal expected, ps.path, "defaults to GEM_PATH"
end
@@ -25,7 +25,7 @@ class TestGemPathSupport < Gem::TestCase
assert_equal File.join(@tempdir, "foo"), ps.home
- expected = util_path + [File.join(@tempdir, 'foo')]
+ expected = ENV["GEM_PATH"].split(File::PATH_SEPARATOR) + [File.join(@tempdir, 'foo')]
assert_equal expected, ps.path
end
@@ -102,10 +102,6 @@ class TestGemPathSupport < Gem::TestCase
end
end
- def util_path
- ENV["GEM_PATH"].split(File::PATH_SEPARATOR)
- end
-
def test_initialize_spec
ENV["GEM_SPEC_CACHE"] = nil
diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb
index aae0250801a..8029035db1a 100644
--- a/test/rubygems/test_gem_platform.rb
+++ b/test/rubygems/test_gem_platform.rb
@@ -122,6 +122,7 @@ class TestGemPlatform < Gem::TestCase
'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'],
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index 1bae9247fe9..5ce420b91a8 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -241,6 +241,36 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert File.exist?(a1_cache_gem)
end
+ def test_download_with_token
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ fetcher = util_fuck_with_fetcher a1_data
+
+ a1_cache_gem = @a1.cache_file
+ 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)
+ end
+
+ def test_download_with_x_oauth_basic
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ fetcher = util_fuck_with_fetcher a1_data
+
+ a1_cache_gem = @a1.cache_file
+ 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)
+ end
+
def test_download_with_encoded_auth
a1_data = nil
File.open @a1_gem, 'rb' do |fp|
diff --git a/test/rubygems/test_gem_request.rb b/test/rubygems/test_gem_request.rb
index 780150d6396..66477be7bc0 100644
--- a/test/rubygems/test_gem_request.rb
+++ b/test/rubygems/test_gem_request.rb
@@ -185,7 +185,7 @@ class TestGemRequest < Gem::TestCase
end
def test_fetch
- uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ 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)
@@ -197,31 +197,57 @@ class TestGemRequest < Gem::TestCase
end
def test_fetch_basic_auth
- uri = URI.parse "https://user:pass@example.rubygems/specs.#{Gem.marshal_version}"
+ 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|
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
- @request.fetch
+ use_ui @ui do
+ @request = make_request(uri, 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
+ assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}"
end
def test_fetch_basic_auth_encoded
- uri = URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}"
+ Gem.configuration.verbose = :really
+ uri = Gem::Uri.new(URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}")
+
conn = util_stub_net_http(:body => :junk, :code => 200) do |c|
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
- @request.fetch
+ use_ui @ui do
+ @request = make_request(uri, 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
+ 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}")
+
+ 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.fetch
+ end
+ c
+ end
+
+ 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 = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ 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)
@request.fetch
@@ -232,7 +258,7 @@ class TestGemRequest < Gem::TestCase
end
def test_fetch_unmodified
- uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ uri = Gem::Uri.new(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)
diff --git a/test/rubygems/test_gem_resolver_installer_set.rb b/test/rubygems/test_gem_resolver_installer_set.rb
index 66857943c97..928a16b9d35 100644
--- a/test/rubygems/test_gem_resolver_installer_set.rb
+++ b/test/rubygems/test_gem_resolver_installer_set.rb
@@ -64,6 +64,24 @@ class TestGemResolverInstallerSet < Gem::TestCase
assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
end
+ def test_add_always_install_prerelease_github_problem
+ spec_fetcher do |fetcher|
+ 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'),
+ ]))
+
+ set = Gem::Resolver::InstallerSet.new :both
+
+ set.add_always_install dep('a')
+
+ assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
+ end
+
def test_add_always_install_prerelease_only
spec_fetcher do |fetcher|
fetcher.gem 'a', '3.a'
diff --git a/test/rubygems/test_gem_security.rb b/test/rubygems/test_gem_security.rb
index 2eabbea3bfe..d04bd4a8bd8 100644
--- a/test/rubygems/test_gem_security.rb
+++ b/test/rubygems/test_gem_security.rb
@@ -12,6 +12,7 @@ end
class TestGemSecurity < Gem::TestCase
CHILD_KEY = load_key 'child'
+ EC_KEY = load_key 'private_ec', 'Foo bar'
ALTERNATE_CERT = load_cert 'child'
CHILD_CERT = load_cert 'child'
@@ -103,11 +104,38 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_create_key
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
assert_kind_of OpenSSL::PKey::RSA, key
end
+ def test_class_create_key_downcases
+ key = @SEC.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
+ @SEC.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, @SEC.get_public_key(PRIVATE_KEY).to_pem
+ end
+
+ def test_class_get_public_key_ec
+ pkey = @SEC.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
@@ -259,7 +287,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
path = File.join @tempdir, 'test-private_key.pem'
@@ -273,7 +301,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write_encrypted
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
path = File.join @tempdir, 'test-private_encrypted_key.pem'
@@ -289,7 +317,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write_encrypted_cipher
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
path = File.join @tempdir, 'test-private_encrypted__with_non_default_cipher_key.pem'
diff --git a/test/rubygems/test_gem_source_fetch_problem.rb b/test/rubygems/test_gem_source_fetch_problem.rb
index 0b1472c0c60..816407781d4 100644
--- a/test/rubygems/test_gem_source_fetch_problem.rb
+++ b/test/rubygems/test_gem_source_fetch_problem.rb
@@ -23,4 +23,14 @@ class TestGemSourceFetchProblem < Gem::TestCase
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'
+
+ sf = Gem::SourceFetchProblem.new source, error
+ sf.wordy
+
+ assert_match 'secret', source.uri.to_s
+ end
end
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 88afa3faa01..582813c01dd 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -127,265 +127,241 @@ end
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
+ 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"
-
- install_specs d1, d2, d3, e, c1, c2, b1, b2, a1
+ 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
- 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"
+ 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
- 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"
+ 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
- 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
##
@@ -509,41 +485,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
@@ -2146,43 +2118,39 @@ 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
@@ -2781,6 +2749,34 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
end
assert_equal %("#{f}" or "#{t}" is not a description), e.message
+
+ # Adding #{f} anywhere after the start of the description should be fine.
+ @a1.description = "(some description) #{f}"
+
+ assert_nothing_raised do
+ @a1.validate
+ end
+
+ # Adding #{t} anywhere after the start of the description should be fine.
+ @a1.description = "(some description) #{t}"
+
+ 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
diff --git a/test/rubygems/test_gem_uri.rb b/test/rubygems/test_gem_uri.rb
new file mode 100644
index 00000000000..7fe572518b6
--- /dev/null
+++ b/test/rubygems/test_gem_uri.rb
@@ -0,0 +1,39 @@
+require_relative 'helper'
+require 'rubygems/uri'
+
+class TestUri < Gem::TestCase
+ def test_to_s_not_string
+ assert_equal "not_a_uri", Gem::Uri.new(:not_a_uri).to_s
+ end
+
+ def test_to_s_invalid_uri
+ assert_equal "https://www.example.com:80index", Gem::Uri.new("https://www.example.com:80index").to_s
+ end
+
+ def test_redacted_with_user_pass
+ assert_equal "https://user:REDACTED@example.com", Gem::Uri.new("https://user:pass@example.com").redacted.to_s
+ end
+
+ def test_redacted_with_token
+ assert_equal "https://REDACTED@example.com", Gem::Uri.new("https://token@example.com").redacted.to_s
+ end
+
+ def test_redacted_with_user_x_oauth_basic
+ assert_equal "https://REDACTED:x-oauth-basic@example.com", Gem::Uri.new("https://token:x-oauth-basic@example.com").redacted.to_s
+ end
+
+ def test_redacted_without_credential
+ assert_equal "https://www.example.com", Gem::Uri.new("https://www.example.com").redacted.to_s
+ end
+
+ def test_redacted_with_invalid_uri
+ assert_equal "https://www.example.com:80index", Gem::Uri.new("https://www.example.com:80index").redacted.to_s
+ end
+
+ def test_redacted_does_not_modify_uri
+ url = 'https://user:password@example.com'
+ uri = Gem::Uri.new(url)
+ 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_rubygems.rb b/test/rubygems/test_rubygems.rb
new file mode 100644
index 00000000000..493b9fdf4a3
--- /dev/null
+++ b/test/rubygems/test_rubygems.rb
@@ -0,0 +1,44 @@
+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
+ assert $?.success?
+ end
+
+ def test_operating_system_other_exceptions
+ 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
+ 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. " \
+ "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
+
+ 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_rubygems_defaults_arg = File.join dir_lib_arg, "lib", "rubygems", "defaults"
+ FileUtils.mkdir_p dir_lib_rubygems_defaults_arg
+
+ operating_system_rb = File.join dir_lib_rubygems_defaults_arg, "operating_system.rb"
+
+ File.open(operating_system_rb, 'w') {|f| f.write content }
+
+ File.join dir_lib_arg, "lib"
+ 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") }) }]
+ end
+end
diff --git a/test/runner.rb b/test/runner.rb
index d23d9f0bd2e..a24cfa31c63 100644
--- a/test/runner.rb
+++ b/test/runner.rb
@@ -5,7 +5,7 @@ ENV["GEM_SKIP"] = ENV["GEM_HOME"] = ENV["GEM_PATH"] = "".freeze
ENV.delete("RUBY_CODESIGN")
# Get bundled gems on load path
-Dir.glob("#{__dir__}/../gems/*/*.gemspec")
+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") }
diff --git a/test/socket/test_addrinfo.rb b/test/socket/test_addrinfo.rb
index e068c6c216a..5bd34cd5eb8 100644
--- a/test/socket/test_addrinfo.rb
+++ b/test/socket/test_addrinfo.rb
@@ -586,7 +586,7 @@ class TestSocketAddrinfo < Test::Unit::TestCase
ai = ipv6(addr)
begin
assert(ai.ipv4? || ai.send(meth), "ai=#{addr_exp}; ai.ipv4? || .#{meth}")
- rescue Minitest::Assertion
+ rescue Test::Unit::AssertionFailedError
if /aix/ =~ RUBY_PLATFORM
skip "Known bug in IN6_IS_ADDR_V4COMPAT and IN6_IS_ADDR_V4MAPPED on AIX"
end
diff --git a/test/socket/test_basicsocket.rb b/test/socket/test_basicsocket.rb
index 7b1c9b4a06d..02e393d4e8f 100644
--- a/test/socket/test_basicsocket.rb
+++ b/test/socket/test_basicsocket.rb
@@ -32,7 +32,7 @@ class TestSocket_BasicSocket < Test::Unit::TestCase
n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
assert_equal([0].pack("i"), n.data)
- rescue Minitest::Assertion
+ rescue Test::Unit::AssertionFailedError
s.close
if /aix/ =~ RUBY_PLATFORM
skip "Known bug in getsockopt(2) on AIX"
diff --git a/test/test_ipaddr.rb b/test/test_ipaddr.rb
index 7b3a199bf3e..2afe749db3e 100644
--- a/test/test_ipaddr.rb
+++ b/test/test_ipaddr.rb
@@ -43,6 +43,17 @@ class TC_IPAddr < Test::Unit::TestCase
assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
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)
@@ -87,10 +98,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 +131,23 @@ 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"))
+ # 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"))
+
+ # Invalid parameters
+ assert_raise(IPAddr::AddressFamilyError) {
+ IPAddr.ntop("192.168.1.1")
+ }
+
+ assert_raise(IPAddr::AddressFamilyError) {
+ IPAddr.ntop("\xC0\xA8\x01\xFF1")
+ }
+ end
+
def test_ipv4_compat
a = IPAddr.new("::192.168.1.2")
assert_equal("::192.168.1.2", a.to_s)
@@ -200,6 +232,29 @@ 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_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
end
class TC_Operator < Test::Unit::TestCase
@@ -295,6 +350,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
diff --git a/test/test_timeout.rb b/test/test_timeout.rb
index 71607ed6805..74b65f119d2 100644
--- a/test/test_timeout.rb
+++ b/test/test_timeout.rb
@@ -3,6 +3,17 @@ require 'test/unit'
require 'timeout'
class TestTimeout < Test::Unit::TestCase
+
+ def test_non_timing_out_code_is_successful
+ assert_nothing_raised do
+ assert_equal :ok, Timeout.timeout(1){ :ok }
+ 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]") {
diff --git a/test/uri/test_http.rb b/test/uri/test_http.rb
index cc19046c8f4..748e90a3220 100644
--- a/test/uri/test_http.rb
+++ b/test/uri/test_http.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: false
require 'test/unit'
require 'uri/http'
+require 'uri/https'
module URI
@@ -24,14 +25,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 +52,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,6 +67,20 @@ class TestHTTP < Test::Unit::TestCase
u.select(:scheme, :host, :not_exist, :port)
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/zlib/test_zlib.rb b/test/zlib/test_zlib.rb
index 4780bc077bb..a629c0c902a 100644
--- a/test/zlib/test_zlib.rb
+++ b/test/zlib/test_zlib.rb
@@ -1319,7 +1319,7 @@ if defined? Zlib
assert_equal(0x02820145, Zlib.adler32_combine(one, two, 1))
rescue NotImplementedError
skip "adler32_combine is not implemented"
- rescue Minitest::Assertion
+ 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"
end
@@ -1354,7 +1354,7 @@ if defined? Zlib
assert_equal(0x8c736521, Zlib.crc32_combine(one, two, 1))
rescue NotImplementedError
skip "crc32_combine is not implemented"
- rescue Minitest::Assertion
+ 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"
end