summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.github/actions/compilers/entrypoint.sh4
-rw-r--r--.github/actions/launchable/setup/action.yml2
-rw-r--r--NEWS.md2
-rw-r--r--ast.c10
-rw-r--r--ext/date/date_core.c23
-rw-r--r--gc.c2
-rw-r--r--lib/rubygems.rb2
-rw-r--r--lib/rubygems/bundler_integration.rb23
-rw-r--r--node_dump.c6
-rw-r--r--object.c2
-rw-r--r--parse.y42
-rw-r--r--rubyparser.h4
-rw-r--r--shape.c2
-rw-r--r--spec/ruby/optional/capi/digest_spec.rb6
-rw-r--r--test/date/test_date.rb4
-rw-r--r--test/date/test_switch_hitter.rb5
-rw-r--r--test/ruby/test_ast.rb18
-rw-r--r--test/ruby/test_gc.rb8
-rw-r--r--test/ruby/test_variable.rb1
-rw-r--r--tool/lib/dump.gdb17
-rw-r--r--tool/lib/dump.lldb13
-rw-r--r--tool/lib/envutil.rb75
-rw-r--r--tool/lib/test/unit.rb8
23 files changed, 229 insertions, 50 deletions
diff --git a/.github/actions/compilers/entrypoint.sh b/.github/actions/compilers/entrypoint.sh
index ad9fa87a11..16c3f9f21d 100755
--- a/.github/actions/compilers/entrypoint.sh
+++ b/.github/actions/compilers/entrypoint.sh
@@ -123,7 +123,7 @@ setup_launchable() {
--flavor cppflags="${INPUT_CPPFLAGS}" \
--test-suite test-spec \
> "${builddir}"/${test_spec_session_file} \
- spec_opts+=--launchable-test-reports="${test_spec_report_path}" || :
+ && spec_opts+=--launchable-test-reports="${test_spec_report_path}" || :
fi
}
launchable_record_test() {
@@ -143,7 +143,7 @@ if [ "$LAUNCHABLE_ENABLED" = "true" ]; then
btest_session_file='launchable_btest_session.txt'
test_spec_session_file='launchable_test_spec_session.txt'
setup_pid=$$
- (sleep 180; echo "setup_launchable timed out; killing"; kill -INT "$setup_pid" 2> /dev/null) & sleep_pid=$!
+ (sleep 180; echo "setup_launchable timed out; killing"; kill -INT "-$setup_pid" 2> /dev/null) & sleep_pid=$!
launchable_failed=false
trap "launchable_failed=true" INT
setup_launchable
diff --git a/.github/actions/launchable/setup/action.yml b/.github/actions/launchable/setup/action.yml
index 09a70516ae..07990a885b 100644
--- a/.github/actions/launchable/setup/action.yml
+++ b/.github/actions/launchable/setup/action.yml
@@ -244,7 +244,7 @@ runs:
post: |
rm -f "${test_all_session_file}"
rm -f "${btest_session_file}"
- rm -f "${test_spec_session_file}
+ rm -f "${test_spec_session_file}"
if: always() && steps.setup-launchable.outcome == 'success'
env:
test_all_session_file: ${{ steps.global.outputs.test_all_session_file }}
diff --git a/NEWS.md b/NEWS.md
index b332164e25..350d9a04f0 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -165,7 +165,7 @@ The following bundled gems are updated.
## Compatibility issues
-* The following methdos were removed from Ractor due because of `Ractor::Port`:
+* The following methods were removed from Ractor due because of `Ractor::Port`:
* `Ractor.yield`
* `Ractor#take`
diff --git a/ast.c b/ast.c
index b98fba6fab..dde42e5921 100644
--- a/ast.c
+++ b/ast.c
@@ -812,6 +812,16 @@ node_locations(VALUE ast_value, const NODE *node)
location_new(&RNODE_CLASS(node)->class_keyword_loc),
location_new(&RNODE_CLASS(node)->inheritance_operator_loc),
location_new(&RNODE_CLASS(node)->end_keyword_loc));
+ case NODE_COLON2:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_COLON2(node)->delimiter_loc),
+ location_new(&RNODE_COLON2(node)->name_loc));
+ case NODE_COLON3:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_COLON3(node)->delimiter_loc),
+ location_new(&RNODE_COLON3(node)->name_loc));
case NODE_DOT2:
return rb_ary_new_from_args(2,
location_new(nd_code_loc(node)),
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index 44dbf4fbcf..dbee067f6b 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -1599,7 +1599,7 @@ m_ajd(union DateData *x)
if (simple_dat_p(x)) {
r = m_real_jd(x);
- if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) {
+ if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2) && FIX2LONG(r) >= (FIXNUM_MIN + 1) / 2) {
long ir = FIX2LONG(r);
ir = ir * 2 - 1;
return rb_rational_new2(LONG2FIX(ir), INT2FIX(2));
@@ -6936,13 +6936,24 @@ d_lite_eql_p(VALUE self, VALUE other)
static VALUE
d_lite_hash(VALUE self)
{
- st_index_t v, h[4];
+ st_index_t v, h[5];
+ VALUE nth;
get_d1(self);
- h[0] = m_nth(dat);
- h[1] = m_jd(dat);
- h[2] = m_df(dat);
- h[3] = m_sf(dat);
+ nth = m_nth(dat);
+
+ if (FIXNUM_P(nth)) {
+ h[0] = 0;
+ h[1] = (st_index_t)nth;
+ } else {
+ h[0] = 1;
+ h[1] = (st_index_t)FIX2LONG(rb_hash(nth));
+ }
+
+ h[2] = m_jd(dat);
+ h[3] = m_df(dat);
+ h[4] = m_sf(dat);
+
v = rb_memhash(h, sizeof(h));
return ST2FIX(v);
}
diff --git a/gc.c b/gc.c
index eacd8dae86..e920348a12 100644
--- a/gc.c
+++ b/gc.c
@@ -4166,7 +4166,7 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
break;
}
case RB_GC_VM_WEAK_TABLE_COUNT:
- rb_bug("Unreacheable");
+ rb_bug("Unreachable");
default:
rb_bug("rb_gc_vm_weak_table_foreach: unknown table %d", table);
}
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 1225cbe5cb..fc97f5ff25 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -1144,7 +1144,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(path)
require_relative "rubygems/user_interaction"
- require "bundler"
+ require_relative "rubygems/bundler_integration"
begin
Gem::DefaultUserInteraction.use_ui(ui) do
Bundler.ui.silence do
diff --git a/lib/rubygems/bundler_integration.rb b/lib/rubygems/bundler_integration.rb
new file mode 100644
index 0000000000..28228e2398
--- /dev/null
+++ b/lib/rubygems/bundler_integration.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require "bundler/version"
+
+if Bundler::VERSION > "2.6.9"
+ require "bundler"
+else
+ previous_platforms = {}
+
+ platform_const_list = ["JAVA", "MSWIN", "MSWIN64", "MINGW", "X64_MINGW_LEGACY", "X64_MINGW", "UNIVERSAL_MINGW", "WINDOWS", "X64_LINUX", "X64_LINUX_MUSL"]
+
+ platform_const_list.each do |platform|
+ previous_platforms[platform] = Gem::Platform.const_get(platform)
+ Gem::Platform.send(:remove_const, platform)
+ end
+
+ require "bundler"
+
+ platform_const_list.each do |platform|
+ Gem::Platform.send(:remove_const, platform) if Gem::Platform.const_defined?(platform)
+ Gem::Platform.const_set(platform, previous_platforms[platform])
+ end
+end
diff --git a/node_dump.c b/node_dump.c
index 24711f3d97..ff5cc268ec 100644
--- a/node_dump.c
+++ b/node_dump.c
@@ -1027,8 +1027,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: [nd_head]::[nd_mid]");
ANN("example: M::C");
F_ID(nd_mid, RNODE_COLON2, "constant name");
- LAST_NODE;
F_NODE(nd_head, RNODE_COLON2, "receiver");
+ F_LOC(delimiter_loc, RNODE_COLON2);
+ LAST_NODE;
+ F_LOC(name_loc, RNODE_COLON2);
return;
case NODE_COLON3:
@@ -1036,6 +1038,8 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: ::[nd_mid]");
ANN("example: ::Object");
F_ID(nd_mid, RNODE_COLON3, "constant name");
+ F_LOC(delimiter_loc, RNODE_COLON3);
+ F_LOC(name_loc, RNODE_COLON3);
return;
case NODE_DOT2:
diff --git a/object.c b/object.c
index 03474389fd..ae1a8aa406 100644
--- a/object.c
+++ b/object.c
@@ -378,7 +378,7 @@ init_copy(VALUE dest, VALUE obj)
RBASIC(dest)->flags |= RBASIC(obj)->flags & T_MASK;
switch (BUILTIN_TYPE(obj)) {
case T_IMEMO:
- rb_bug("Unreacheable");
+ rb_bug("Unreachable");
break;
case T_CLASS:
case T_MODULE:
diff --git a/parse.y b/parse.y
index 156c78c0c6..3138061b98 100644
--- a/parse.y
+++ b/parse.y
@@ -1146,8 +1146,8 @@ static rb_node_undef_t *rb_node_undef_new(struct parser_params *p, NODE *nd_unde
static rb_node_class_t *rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *inheritance_operator_loc, const YYLTYPE *end_keyword_loc);
static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc);
static rb_node_sclass_t *rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc);
-static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc);
+static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc);
+static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc);
static rb_node_dot2_t *rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc);
static rb_node_dot3_t *rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc);
static rb_node_self_t *rb_node_self_new(struct parser_params *p, const YYLTYPE *loc);
@@ -1254,8 +1254,8 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_CLASS(n,b,s,loc,ck_loc,io_loc,ek_loc) (NODE *)rb_node_class_new(p,n,b,s,loc,ck_loc,io_loc,ek_loc)
#define NEW_MODULE(n,b,loc) (NODE *)rb_node_module_new(p,n,b,loc)
#define NEW_SCLASS(r,b,loc) (NODE *)rb_node_sclass_new(p,r,b,loc)
-#define NEW_COLON2(c,i,loc) (NODE *)rb_node_colon2_new(p,c,i,loc)
-#define NEW_COLON3(i,loc) (NODE *)rb_node_colon3_new(p,i,loc)
+#define NEW_COLON2(c,i,loc,d_loc,n_loc) (NODE *)rb_node_colon2_new(p,c,i,loc,d_loc,n_loc)
+#define NEW_COLON3(i,loc,d_loc,n_loc) (NODE *)rb_node_colon3_new(p,i,loc,d_loc,n_loc)
#define NEW_DOT2(b,e,loc,op_loc) (NODE *)rb_node_dot2_new(p,b,e,loc,op_loc)
#define NEW_DOT3(b,e,loc,op_loc) (NODE *)rb_node_dot3_new(p,b,e,loc,op_loc)
#define NEW_SELF(loc) (NODE *)rb_node_self_new(p,loc)
@@ -3067,13 +3067,13 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
| primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt rhs
{
YYLTYPE loc = code_loc_gen(&@primary_value, &@tCONSTANT);
- $$ = new_const_op_assign(p, NEW_COLON2($primary_value, $tCONSTANT, &loc), $tOP_ASGN, $rhs, $lex_ctxt, &@$);
+ $$ = new_const_op_assign(p, NEW_COLON2($primary_value, $tCONSTANT, &loc, &@tCOLON2, &@tCONSTANT), $tOP_ASGN, $rhs, $lex_ctxt, &@$);
/*% ripper: opassign!(const_path_field!($:1, $:3), $:4, $:6) %*/
}
| tCOLON3 tCONSTANT tOP_ASGN lex_ctxt rhs
{
YYLTYPE loc = code_loc_gen(&@tCOLON3, &@tCONSTANT);
- $$ = new_const_op_assign(p, NEW_COLON3($tCONSTANT, &loc), $tOP_ASGN, $rhs, $lex_ctxt, &@$);
+ $$ = new_const_op_assign(p, NEW_COLON3($tCONSTANT, &loc, &@tCOLON3, &@tCONSTANT), $tOP_ASGN, $rhs, $lex_ctxt, &@$);
/*% ripper: opassign!(top_const_field!($:2), $:3, $:5) %*/
}
| backref tOP_ASGN lex_ctxt rhs
@@ -3756,12 +3756,12 @@ mlhs_node : user_or_keyword_variable
| primary_value tCOLON2 tCONSTANT
{
/*% ripper: const_path_field!($:1, $:3) %*/
- $$ = const_decl(p, NEW_COLON2($1, $3, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON2($1, $3, &@$, &@2, &@3), &@$);
}
| tCOLON3 tCONSTANT
{
/*% ripper: top_const_field!($:2) %*/
- $$ = const_decl(p, NEW_COLON3($2, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON3($2, &@$, &@1, &@2), &@$);
}
| backref
{
@@ -3794,12 +3794,12 @@ lhs : user_or_keyword_variable
| primary_value tCOLON2 tCONSTANT
{
/*% ripper: const_path_field!($:1, $:3) %*/
- $$ = const_decl(p, NEW_COLON2($1, $3, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON2($1, $3, &@$, &@2, &@3), &@$);
}
| tCOLON3 tCONSTANT
{
/*% ripper: top_const_field!($:2) %*/
- $$ = const_decl(p, NEW_COLON3($2, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON3($2, &@$, &@1, &@2), &@$);
}
| backref
{
@@ -3822,17 +3822,17 @@ cname : tIDENTIFIER
cpath : tCOLON3 cname
{
- $$ = NEW_COLON3($2, &@$);
+ $$ = NEW_COLON3($2, &@$, &@1, &@2);
/*% ripper: top_const_ref!($:2) %*/
}
| cname
{
- $$ = NEW_COLON2(0, $1, &@$);
+ $$ = NEW_COLON2(0, $1, &@$, &NULL_LOC, &@1);
/*% ripper: const_ref!($:1) %*/
}
| primary_value tCOLON2 cname
{
- $$ = NEW_COLON2($1, $3, &@$);
+ $$ = NEW_COLON2($1, $3, &@$, &@2, &@3);
/*% ripper: const_path_ref!($:1, $:3) %*/
}
;
@@ -4385,12 +4385,12 @@ primary : inline_primary
}
| primary_value tCOLON2 tCONSTANT
{
- $$ = NEW_COLON2($1, $3, &@$);
+ $$ = NEW_COLON2($1, $3, &@$, &@2, &@3);
/*% ripper: const_path_ref!($:1, $:3) %*/
}
| tCOLON3 tCONSTANT
{
- $$ = NEW_COLON3($2, &@$);
+ $$ = NEW_COLON3($2, &@$, &@1, &@2);
/*% ripper: top_const_ref!($:2) %*/
}
| tLBRACK aref_args ']'
@@ -5810,12 +5810,12 @@ p_expr_ref : '^' tLPAREN expr_value rparen
p_const : tCOLON3 cname
{
- $$ = NEW_COLON3($2, &@$);
+ $$ = NEW_COLON3($2, &@$, &@1, &@2);
/*% ripper: top_const_ref!($:2) %*/
}
| p_const tCOLON2 cname
{
- $$ = NEW_COLON2($1, $3, &@$);
+ $$ = NEW_COLON2($1, $3, &@$, &@2, &@3);
/*% ripper: const_path_ref!($:1, $:3) %*/
}
| tCONSTANT
@@ -11553,20 +11553,24 @@ rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd
}
static rb_node_colon2_t *
-rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc)
+rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc)
{
rb_node_colon2_t *n = NODE_NEWNODE(NODE_COLON2, rb_node_colon2_t, loc);
n->nd_head = nd_head;
n->nd_mid = nd_mid;
+ n->delimiter_loc = *delimiter_loc;
+ n->name_loc = *name_loc;
return n;
}
static rb_node_colon3_t *
-rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc)
+rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc)
{
rb_node_colon3_t *n = NODE_NEWNODE(NODE_COLON3, rb_node_colon3_t, loc);
n->nd_mid = nd_mid;
+ n->delimiter_loc = *delimiter_loc;
+ n->name_loc = *name_loc;
return n;
}
diff --git a/rubyparser.h b/rubyparser.h
index 7525069fcb..c63929abb2 100644
--- a/rubyparser.h
+++ b/rubyparser.h
@@ -915,12 +915,16 @@ typedef struct RNode_COLON2 {
struct RNode *nd_head;
ID nd_mid;
+ rb_code_location_t delimiter_loc;
+ rb_code_location_t name_loc;
} rb_node_colon2_t;
typedef struct RNode_COLON3 {
NODE node;
ID nd_mid;
+ rb_code_location_t delimiter_loc;
+ rb_code_location_t name_loc;
} rb_node_colon3_t;
/* NODE_DOT2, NODE_DOT3, NODE_FLIP2, NODE_FLIP3 */
diff --git a/shape.c b/shape.c
index 06dcb8d610..20153b1c98 100644
--- a/shape.c
+++ b/shape.c
@@ -1262,7 +1262,7 @@ rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id)
}
else {
if (flags_heap_index) {
- rb_bug("shape_id indicate heap_index > 0 but objet is not T_OBJECT: %s", rb_obj_info(obj));
+ rb_bug("shape_id indicate heap_index > 0 but object is not T_OBJECT: %s", rb_obj_info(obj));
}
}
diff --git a/spec/ruby/optional/capi/digest_spec.rb b/spec/ruby/optional/capi/digest_spec.rb
index c753733906..65c5ecebb1 100644
--- a/spec/ruby/optional/capi/digest_spec.rb
+++ b/spec/ruby/optional/capi/digest_spec.rb
@@ -1,6 +1,10 @@
require_relative 'spec_helper'
-require 'fiddle'
+begin
+ require 'fiddle'
+rescue LoadError
+ return
+end
load_extension('digest')
diff --git a/test/date/test_date.rb b/test/date/test_date.rb
index 3f9c893efa..7e37fc94d2 100644
--- a/test/date/test_date.rb
+++ b/test/date/test_date.rb
@@ -135,6 +135,10 @@ class TestDate < Test::Unit::TestCase
assert_equal(9, h[DateTime.new(1999,5,25)])
h = {}
+ h[Date.new(3171505571716611468830131104691,2,19)] = 0
+ assert_equal(true, h.key?(Date.new(3171505571716611468830131104691,2,19)))
+
+ h = {}
h[DateTime.new(1999,5,23)] = 0
h[DateTime.new(1999,5,24)] = 1
h[DateTime.new(1999,5,25)] = 2
diff --git a/test/date/test_switch_hitter.rb b/test/date/test_switch_hitter.rb
index bdf299e030..cc75782537 100644
--- a/test/date/test_switch_hitter.rb
+++ b/test/date/test_switch_hitter.rb
@@ -97,6 +97,11 @@ class TestSH < Test::Unit::TestCase
[d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
end
+ def test_ajd
+ assert_equal(Date.civil(2008, 1, 16).ajd, 4908963r/2)
+ assert_equal(Date.civil(-11082381539297990, 2, 19).ajd, -8095679714453739481r/2)
+ end
+
def test_ordinal
d = Date.ordinal
assert_equal([-4712, 1], [d.year, d.yday])
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index 72a0d821a0..d22823470b 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -1397,6 +1397,24 @@ dummy
assert_locations(node.children[-1].locations, [[1, 0, 1, 16], [1, 0, 1, 5], [1, 8, 1, 9], [1, 13, 1, 16]])
end
+ def test_colon2_locations
+ node = ast_parse("A::B")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 4], [1, 1, 1, 3], [1, 3, 1, 4]])
+
+ node = ast_parse("A::B::C")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 7], [1, 4, 1, 6], [1, 6, 1, 7]])
+ assert_locations(node.children[-1].children[0].locations, [[1, 0, 1, 4], [1, 1, 1, 3], [1, 3, 1, 4]])
+ end
+
+ def test_colon3_locations
+ node = ast_parse("::A")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 3], [1, 0, 1, 2], [1, 2, 1, 3]])
+
+ node = ast_parse("::A::B")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 3, 1, 5], [1, 5, 1, 6]])
+ assert_locations(node.children[-1].children[0].locations, [[1, 0, 1, 3], [1, 0, 1, 2], [1, 2, 1, 3]])
+ end
+
def test_dot2_locations
node = ast_parse("1..2")
assert_locations(node.children[-1].locations, [[1, 0, 1, 4], [1, 1, 1, 3]])
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index daa645b349..3516cefedf 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -393,12 +393,10 @@ class TestGc < Test::Unit::TestCase
# Create some objects and place it in a WeakMap
wmap = ObjectSpace::WeakMap.new
- ary = Array.new(count)
- enum = count.times
- enum.each.with_index do |i|
+ ary = Array.new(count) do |i|
obj = Object.new
- ary[i] = obj
wmap[obj] = nil
+ obj
end
# Run full GC to collect stats about weak references
@@ -421,7 +419,7 @@ class TestGc < Test::Unit::TestCase
GC.start
# Sometimes the WeakMap has a few elements, which might be held on by registers.
- assert_operator(wmap.size, :<=, 2)
+ assert_operator(wmap.size, :<=, count / 1000)
assert_operator(GC.latest_gc_info(:weak_references_count), :<=, before_weak_references_count - count + error_tolerance)
assert_operator(GC.latest_gc_info(:retained_weak_references_count), :<=, before_retained_weak_references_count - count + error_tolerance)
diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb
index d8d0a1a393..984045e05d 100644
--- a/test/ruby/test_variable.rb
+++ b/test/ruby/test_variable.rb
@@ -408,6 +408,7 @@ class TestVariable < Test::Unit::TestCase
end
def test_exivar_resize_with_compaction_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
objs = 10_000.times.map do
ExIvar.new
end
diff --git a/tool/lib/dump.gdb b/tool/lib/dump.gdb
new file mode 100644
index 0000000000..56b420a546
--- /dev/null
+++ b/tool/lib/dump.gdb
@@ -0,0 +1,17 @@
+set height 0
+set width 0
+set confirm off
+
+echo \n>>> Threads\n\n
+info threads
+
+echo \n>>> Machine level backtrace\n\n
+thread apply all info stack full
+
+echo \n>>> Dump Ruby level backtrace (if possible)\n\n
+call rb_vmdebug_stack_dump_all_threads()
+call fflush(stderr)
+
+echo ">>> Finish\n"
+detach
+quit
diff --git a/tool/lib/dump.lldb b/tool/lib/dump.lldb
new file mode 100644
index 0000000000..ed9cb89010
--- /dev/null
+++ b/tool/lib/dump.lldb
@@ -0,0 +1,13 @@
+script print("\n>>> Threads\n\n")
+thread list
+
+script print("\n>>> Machine level backtrace\n\n")
+thread backtrace all
+
+script print("\n>>> Dump Ruby level backtrace (if possible)\n\n")
+call rb_vmdebug_stack_dump_all_threads()
+call fflush(stderr)
+
+script print(">>> Finish\n")
+detach
+quit
diff --git a/tool/lib/envutil.rb b/tool/lib/envutil.rb
index 65c86c1685..573fd5122c 100644
--- a/tool/lib/envutil.rb
+++ b/tool/lib/envutil.rb
@@ -79,6 +79,70 @@ module EnvUtil
end
module_function :timeout
+ class Debugger
+ @list = []
+
+ attr_accessor :name
+
+ def self.register(name, &block)
+ @list << new(name, &block)
+ end
+
+ def initialize(name, &block)
+ @name = name
+ instance_eval(&block)
+ end
+
+ def usable?; false; end
+
+ def start(pid, *args) end
+
+ def dump(pid, timeout: 60, reprieve: timeout&.div(4))
+ dpid = start(pid, *command_file(File.join(__dir__, "dump.#{name}")))
+ rescue Errno::ENOENT
+ return
+ else
+ return unless dpid
+ [[timeout, :TERM], [reprieve, :KILL]].find do |t, sig|
+ return EnvUtil.timeout(t) {Process.wait(dpid)}
+ rescue Timeout::Error
+ Process.kill(sig, dpid)
+ end
+ true
+ end
+
+ # sudo -n: --non-interactive
+ PRECOMMAND = (%[sudo -n] if /darwin/ =~ RUBY_PLATFORM)
+
+ def spawn(*args, **opts)
+ super(*PRECOMMAND, *args, **opts)
+ end
+
+ register("gdb") do
+ class << self
+ def usable?; system(*%w[gdb --batch --quiet --nx -ex exit]); end
+ def start(pid, *args)
+ spawn(*%w[gdb --batch --quiet --pid #{pid}], *args)
+ end
+ def command_file(file) "--command=#{file}"; end
+ end
+ end
+
+ register("lldb") do
+ class << self
+ def usable?; system(*%w[lldb -Q --no-lldbinit -o exit]); end
+ def start(pid, *args)
+ spawn(*%w[lldb --batch -Q --attach-pid #{pid}])
+ end
+ def command_file(file) ["--source", file]; end
+ end
+ end
+
+ def self.search
+ @debugger ||= @list.find(&:usable?)
+ end
+ end
+
def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1)
reprieve = apply_timeout_scale(reprieve) if reprieve
@@ -94,17 +158,10 @@ module EnvUtil
pgroup = pid
end
- lldb = true if /darwin/ =~ RUBY_PLATFORM
-
while signal = signals.shift
- if lldb and [:ABRT, :KILL].include?(signal)
- lldb = false
- # sudo -n: --non-interactive
- # lldb -p: attach
- # -o: run command
- system(*%W[sudo -n lldb -p #{pid} --batch -o bt\ all -o call\ rb_vmdebug_stack_dump_all_threads() -o quit])
- true
+ if (dbg = Debugger.search) and [:ABRT, :KILL].include?(signal)
+ dbg.dump(pid)
end
begin
diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb
index 9ca29b6e64..7d43e825e1 100644
--- a/tool/lib/test/unit.rb
+++ b/tool/lib/test/unit.rb
@@ -421,6 +421,7 @@ module Test
end
def kill
+ EnvUtil::Debugger.search&.dump(@pid)
signal = RUBY_PLATFORM =~ /mswin|mingw/ ? :KILL : :SEGV
Process.kill(signal, @pid)
warn "worker #{to_s} does not respond; #{signal} is sent"
@@ -1298,10 +1299,15 @@ module Test
parser.on '--repeat-count=NUM', "Number of times to repeat", Integer do |n|
options[:repeat_count] = n
end
+ options[:keep_repeating] = false
+ parser.on '--[no-]keep-repeating', "Keep repeating even failed" do |n|
+ options[:keep_repeating] = true
+ end
end
def _run_anything(type)
@repeat_count = @options[:repeat_count]
+ @keep_repeating = @options[:keep_repeating]
super
end
end
@@ -1623,7 +1629,7 @@ module Test
[(@repeat_count ? "(#{@@current_repeat_count}/#{@repeat_count}) " : ""), type,
t, @test_count.fdiv(t), @assertion_count.fdiv(t)]
end while @repeat_count && @@current_repeat_count < @repeat_count &&
- report.empty? && failures.zero? && errors.zero?
+ (@keep_repeating || report.empty? && failures.zero? && errors.zero?)
output.sync = old_sync if sync