[BUG #20655] Add tests to use rb_ensure and call cont.call
This commit is contained in:
parent
b3baa11ee9
commit
c884db0b5b
Notes:
git
2024-07-30 06:31:44 +00:00
39
ext/-test-/ensure_and_callcc/ensure_and_callcc.c
Normal file
39
ext/-test-/ensure_and_callcc/ensure_and_callcc.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "ruby.h"
|
||||||
|
|
||||||
|
struct require_data {
|
||||||
|
VALUE obj;
|
||||||
|
VALUE fname;
|
||||||
|
};
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
call_require(VALUE arg)
|
||||||
|
{
|
||||||
|
struct require_data *data = (struct require_data *)arg;
|
||||||
|
rb_f_require(data->obj, data->fname);
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
call_ensure(VALUE _)
|
||||||
|
{
|
||||||
|
VALUE v = rb_gv_get("$ensure_called");
|
||||||
|
int called = FIX2INT(v) + 1;
|
||||||
|
rb_gv_set("$ensure_called", INT2FIX(called));
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
require_with_ensure(VALUE self, VALUE fname)
|
||||||
|
{
|
||||||
|
struct require_data data = {
|
||||||
|
.obj = self,
|
||||||
|
.fname = fname
|
||||||
|
};
|
||||||
|
return rb_ensure(call_require, (VALUE)&data, call_ensure, Qnil);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_ensure_and_callcc(void)
|
||||||
|
{
|
||||||
|
rb_define_method(rb_mKernel, "require_with_ensure", require_with_ensure, 1);
|
||||||
|
}
|
5
ext/-test-/ensure_and_callcc/extconf.rb
Normal file
5
ext/-test-/ensure_and_callcc/extconf.rb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# frozen_string_literal: false
|
||||||
|
require "mkmf"
|
||||||
|
|
||||||
|
require_relative "../auto_ext.rb"
|
||||||
|
auto_ext(inc: true)
|
10
test/-ext-/required.rb
Normal file
10
test/-ext-/required.rb
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
require 'continuation'
|
||||||
|
cont = nil
|
||||||
|
a = [*1..10].reject do |i|
|
||||||
|
callcc {|c| cont = c} if !cont and i == 10
|
||||||
|
false
|
||||||
|
end
|
||||||
|
if a.size < 1000
|
||||||
|
a.unshift(:x)
|
||||||
|
cont.call
|
||||||
|
end
|
36
test/-ext-/test_ensure_and_callcc.rb
Normal file
36
test/-ext-/test_ensure_and_callcc.rb
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: us-ascii -*-
|
||||||
|
# frozen_string_literal: false
|
||||||
|
require 'test/unit'
|
||||||
|
|
||||||
|
class TestEnsureAndCallcc < Test::Unit::TestCase
|
||||||
|
require '-test-/ensure_and_callcc'
|
||||||
|
|
||||||
|
def test_bug20655_dir_chdir_using_rb_ensure
|
||||||
|
need_continuation
|
||||||
|
called = 0
|
||||||
|
tmp = nil
|
||||||
|
Dir.chdir('/tmp') do
|
||||||
|
tmp = Dir.pwd
|
||||||
|
cont = nil
|
||||||
|
callcc{|c| cont = c}
|
||||||
|
assert_equal(tmp, Dir.pwd, "BUG #20655: ensure called and pwd was changed unexpectedly")
|
||||||
|
called += 1
|
||||||
|
cont.call if called < 10
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_bug20655_extension_using_rb_ensure
|
||||||
|
need_continuation
|
||||||
|
$ensure_called = 0
|
||||||
|
require_with_ensure(File.join(__dir__, 'required'))
|
||||||
|
assert_equal(1, $ensure_called, "BUG #20655: ensure called unexpectedly in the required script even without exceptions")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def need_continuation
|
||||||
|
unless respond_to?(:callcc, true)
|
||||||
|
EnvUtil.suppress_warning {require 'continuation'}
|
||||||
|
end
|
||||||
|
omit 'requires callcc support' unless respond_to?(:callcc, true)
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user