[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