diff options
Diffstat (limited to 'test')
19 files changed, 194 insertions, 2 deletions
diff --git a/test/digest/test_digest.rb b/test/digest/test_digest.rb index 084eda8b1b..95cce93940 100644 --- a/test/digest/test_digest.rb +++ b/test/digest/test_digest.rb @@ -204,7 +204,7 @@ module TestDigest Data1 => "352441c2", Data2 => "171a3f5f", } - end + end if defined?(Digest::CRC32) class TestBase < Test::Unit::TestCase def test_base diff --git a/test/prism/errors/rescue_modifier_argument_value_alias.txt b/test/prism/errors/rescue_modifier_argument_value_alias.txt new file mode 100644 index 0000000000..e4d0b9dc90 --- /dev/null +++ b/test/prism/errors/rescue_modifier_argument_value_alias.txt @@ -0,0 +1,3 @@ +x = 1 rescue alias a b + ^~~~~ unexpected an `alias` at a non-statement position + diff --git a/test/prism/errors/rescue_modifier_argument_value_not.txt b/test/prism/errors/rescue_modifier_argument_value_not.txt new file mode 100644 index 0000000000..5d066eb43a --- /dev/null +++ b/test/prism/errors/rescue_modifier_argument_value_not.txt @@ -0,0 +1,4 @@ +x = 1 rescue not b + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/rescue_modifier_endless_method_multiple_assignment.txt b/test/prism/errors/rescue_modifier_endless_method_multiple_assignment.txt new file mode 100644 index 0000000000..892f78cc9b --- /dev/null +++ b/test/prism/errors/rescue_modifier_endless_method_multiple_assignment.txt @@ -0,0 +1,4 @@ +def m = foo bar rescue a, b = 1 + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + diff --git a/test/prism/errors/rescue_modifier_multiple_assignment_logical_operator.txt b/test/prism/errors/rescue_modifier_multiple_assignment_logical_operator.txt new file mode 100644 index 0000000000..faca9bf49b --- /dev/null +++ b/test/prism/errors/rescue_modifier_multiple_assignment_logical_operator.txt @@ -0,0 +1,3 @@ +a rescue b, c = d and e + ^~~ unexpected 'and', expecting end-of-input + diff --git a/test/prism/errors/rescue_modifier_multiple_assignment_trailing_comma.txt b/test/prism/errors/rescue_modifier_multiple_assignment_trailing_comma.txt new file mode 100644 index 0000000000..bffd9e7280 --- /dev/null +++ b/test/prism/errors/rescue_modifier_multiple_assignment_trailing_comma.txt @@ -0,0 +1,3 @@ +(a rescue b,) + ^~ unexpected write target + diff --git a/test/prism/errors/rescue_modifier_single_assignment_multiple_assignment.txt b/test/prism/errors/rescue_modifier_single_assignment_multiple_assignment.txt new file mode 100644 index 0000000000..be666ef886 --- /dev/null +++ b/test/prism/errors/rescue_modifier_single_assignment_multiple_assignment.txt @@ -0,0 +1,4 @@ +z = 1 rescue a, b = 1 + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + diff --git a/test/prism/fixtures/rescue_modifier_assignment.txt b/test/prism/fixtures/rescue_modifier_assignment.txt new file mode 100644 index 0000000000..4882835d77 --- /dev/null +++ b/test/prism/fixtures/rescue_modifier_assignment.txt @@ -0,0 +1,3 @@ +x, y = 1 rescue a, b = 1 +x, y = a rescue b, c = 1 +x, y = a rescue b = c d diff --git a/test/prism/fixtures/rescue_modifier_block_command_value.txt b/test/prism/fixtures/rescue_modifier_block_command_value.txt new file mode 100644 index 0000000000..94091f072a --- /dev/null +++ b/test/prism/fixtures/rescue_modifier_block_command_value.txt @@ -0,0 +1,5 @@ +x = foo a do end rescue b +x = foo a do end rescue b, c = 1 +x = a.foo b do end rescue c, d = 1 +x, y = foo a do end rescue b +x += foo a do end rescue b, c = 1 diff --git a/test/prism/fixtures/rescue_modifier_command_value.txt b/test/prism/fixtures/rescue_modifier_command_value.txt new file mode 100644 index 0000000000..7b31adcd2d --- /dev/null +++ b/test/prism/fixtures/rescue_modifier_command_value.txt @@ -0,0 +1,6 @@ +a rescue b = c d +x = foo bar rescue b, c = 1 +x = foo bar rescue b = c d +x += foo bar rescue b, c = 1 +x, y = foo bar rescue b +x, y = foo bar rescue b, c = 1 diff --git a/test/prism/fixtures/rescue_modifier_multiple_assignment.txt b/test/prism/fixtures/rescue_modifier_multiple_assignment.txt new file mode 100644 index 0000000000..79ca21f577 --- /dev/null +++ b/test/prism/fixtures/rescue_modifier_multiple_assignment.txt @@ -0,0 +1,9 @@ +a rescue b, c = 1 +a rescue b, c, d = 1 +a rescue *b, c = 1 +a rescue b, *c = 1 +a rescue b, *c, d = 1 +a rescue *b = 1 +a rescue (b, c), d = 1 +a rescue b.c, d = 1 +a rescue b[0], c = 1 diff --git a/test/prism/fixtures/rescue_modifier_multiple_value.txt b/test/prism/fixtures/rescue_modifier_multiple_value.txt new file mode 100644 index 0000000000..bac7b039a0 --- /dev/null +++ b/test/prism/fixtures/rescue_modifier_multiple_value.txt @@ -0,0 +1,5 @@ +a rescue b = c, d +a rescue b = c, d, e +a rescue b = *c +a rescue b = c, *d +a rescue b = *c, d diff --git a/test/prism/fixtures/rescue_modifier_statement_value.txt b/test/prism/fixtures/rescue_modifier_statement_value.txt new file mode 100644 index 0000000000..d3951a9608 --- /dev/null +++ b/test/prism/fixtures/rescue_modifier_statement_value.txt @@ -0,0 +1,8 @@ +a rescue alias x y +a rescue undef m +a rescue END { b } +a rescue retry +alias x y rescue b +undef m rescue b +END { b } rescue b +x = foo bar rescue retry diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb index 417730a8a7..c4514edd51 100644 --- a/test/prism/locals_test.rb +++ b/test/prism/locals_test.rb @@ -77,6 +77,10 @@ module Prism parts[10] end + def catch_table + parts[12] + end + def instructions parts[13] end @@ -97,6 +101,20 @@ module Prism yield ISeq.new(opnd) end end + + # The handler for a rescue clause is compiled into its own iseq that is + # reachable only through the catch table. Its local table only ever + # holds the implicit `$!` error variable (rescue clauses do not + # introduce user locals of their own -- `rescue => e` puts `e` in the + # enclosing scope), and prism does not model it as a scope, so we treat + # it as transparent and descend straight into any iseqs nested within + # it (e.g. a block or an `END {}` inside a rescue clause). Only + # `:rescue` entries are followed: `:break`/`:next`/`:redo`/`:retry` + # entries either have no iseq or reference one already reachable through + # the instructions, and `:ensure` bodies are compiled inline. + catch_table.each do |entry| + ISeq.new(entry[1]).each_child { |child| yield child } if entry[0] == :rescue && entry[1].is_a?(Array) + end end end diff --git a/test/prism/ruby/parser_test.rb b/test/prism/ruby/parser_test.rb index ad9fa0c92c..856ecedc1d 100644 --- a/test/prism/ruby/parser_test.rb +++ b/test/prism/ruby/parser_test.rb @@ -132,7 +132,6 @@ module Prism "whitequark/lbrace_arg_after_command_args.txt", "whitequark/multiple_pattern_matches.txt", "whitequark/newline_in_hash_argument.txt", - "whitequark/pattern_matching_expr_in_paren.txt", "whitequark/pattern_matching_hash.txt", "whitequark/ruby_bug_14690.txt", "whitequark/ruby_bug_9669.txt", diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb index f74342322f..eefd5b189b 100644 --- a/test/ruby/test_proc.rb +++ b/test/ruby/test_proc.rb @@ -342,6 +342,25 @@ class TestProc < Test::Unit::TestCase assert_equal(9, b) end + # Not named test_curry_* so that test_curry_with_trace does not re-run it + # under set_trace_func (which would be needlessly slow with GC.stress). + def test_proc_curry_keeps_args_alive + # The argument array passed down by `curry` must stay alive across the + # inner call; otherwise GC may reclaim it while it is still read as argv + # and crash with "try to mark T_NONE object". See the RB_GC_GUARD in `curry`. + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}", timeout: 60) + begin; + GC.stress = true + l = ->(a, b, c) { a + b + c } + 30.times do + l1 = l.curry.call(1) + l2 = l1.curry.call(2) + assert_equal(6, l2.curry.call(3)) + assert_equal(6, l1.curry.call(2, 3)) + end + end; + end + def test_lambda? l = proc {} assert_equal(false, l.lambda?) diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index df7054c101..33f13511cb 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1041,6 +1041,55 @@ class TestYJIT < Test::Unit::TestCase RUBY end + def test_bmethod_super_block_forwarding + # super() in a block method forwards the block handler of environment + # it is in. In this test, the block is in a class, which never has + # a block handler, so Parent#foo gets no block. + assert_compiles(<<~RUBY, result: nil) + class Parent + def foo = defined?(yield) + end + + class BmethodSuper < Parent + define_method(:foo) { super() } + end + + BmethodSuper.new.foo {} + RUBY + + # For contrast, the super() here forwards the block passed to add_then_override + # because block with super() is rooted in add_then_override, a "def" method. + assert_compiles(<<~RUBY, result: [1, 2]) + def add_then_override(object) + object.define_singleton_method(:then) { super() } + end + + add_then_override(one = Object.new) { 1 } + add_then_override(two = Object.new) { 2 } + [one.then {}, two.then {}] + RUBY + end + + def test_bug_22116 + # Regression test from report which used to crash during environment escape + # to pass block to Hash.new + assert_compiles(<<~RUBY, call_threshold: 1) + class C + def foo + Hash.new {|h, k| h[k] = [] } + end + end + + class D < C + define_method(:foo) do + super() + end + end + + D.new.foo + RUBY + end + # Tests calling a variadic cfunc with many args def test_build_large_struct assert_compiles(<<~RUBY, insns: %i[opt_send_without_block], call_threshold: 2) diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index a56fea6d51..198301d933 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -382,6 +382,23 @@ class TestZJIT < Test::Unit::TestCase }, call_threshold: 14, num_profiles: 5 end + def test_regression_gc_stress_with_lazy_block_code + assert_compiles ':ok', %q{ + def allocate_array + [1, 2, 3] + end + + begin + GC.stress = true + allocate_array + allocate_array + :ok + ensure + GC.stress = false + end + } + end + def test_exit_tracing # Smoke test: --zjit-trace-exits writes a Fuchsia trace (.fxt) file to /tmp assert_compiles('true', <<~RUBY, extra_args: ['--zjit-trace-exits']) diff --git a/test/test_bundled_gems.rb b/test/test_bundled_gems.rb index 0889584185..884412b416 100644 --- a/test/test_bundled_gems.rb +++ b/test/test_bundled_gems.rb @@ -16,6 +16,39 @@ class TestBundlerGem < Gem::TestCase assert_nil Gem::BUNDLED_GEMS.warning?("csv", specs: {}) end + def test_find_gem_plain_name + assert_equal ["csv", "csv", false], Gem::BUNDLED_GEMS.find_gem("csv") + end + + def test_find_gem_returns_nil_for_non_bundled_gem + assert_nil Gem::BUNDLED_GEMS.find_gem("some_gem") + assert_nil Gem::BUNDLED_GEMS.find_gem("some/nested/gem") + end + + def test_find_gem_exact_mapping + # kconv is provided by the nkf gem; the feature keeps its original name + assert_equal ["kconv", "nkf", false], Gem::BUNDLED_GEMS.find_gem("kconv") + end + + def test_find_gem_dashed_name + # resolv/replace is provided by the resolv-replace gem + assert_equal ["resolv/replace", "resolv-replace", false], Gem::BUNDLED_GEMS.find_gem("resolv/replace") + end + + def test_find_gem_subfeature + assert_equal ["benchmark/ips", "benchmark", true], Gem::BUNDLED_GEMS.find_gem("benchmark/ips") + end + + def test_find_gem_strips_libdir_prefix + path = File.join(::RbConfig::CONFIG.fetch("rubylibdir"), "csv.rb") + assert_equal ["csv", "csv", false], Gem::BUNDLED_GEMS.find_gem(path) + end + + def test_find_gem_strips_archdir_prefix + path = File.join(::RbConfig::CONFIG.fetch("rubyarchdir"), "syslog.so") + assert_equal ["syslog", "syslog", false], Gem::BUNDLED_GEMS.find_gem(path) + end + def test_no_warning_warning assert_nil Gem::BUNDLED_GEMS.warning?("some_gem", specs: {}) assert_nil Gem::BUNDLED_GEMS.warning?("/path/to/some_gem.rb", specs: {}) |
