git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-09-14 15:56:33 +00:00
parent 938465beb0
commit 6479a0163a
31 changed files with 496 additions and 122 deletions

View File

@ -1,3 +0,0 @@
source 'https://rubygems.org'
gem 'mspec', :git => 'https://github.com/ruby/mspec'

View File

@ -27,6 +27,14 @@ ruby/spec is known to be tested in these implementations for every commit:
* [TruffleRuby](https://github.com/graalvm/truffleruby) on Travis
* [Opal](https://github.com/opal/opal/tree/master/spec) on Travis
ruby/spec describes the behavior of Ruby 2.2 and more recent Ruby versions.
More precisely, every latest stable MRI release [passes](https://rubyci.org/) all specs of ruby/spec
(latest 2.2.x, 2.3.x, 2.4.x, etc).
For older specs try these commits:
* Ruby 2.0.0-p647 - [Suite](https://github.com/ruby/spec/commit/245862558761d5abc676843ef74f86c9bcc8ea8d) using [MSpec](https://github.com/ruby/mspec/commit/f90efa068791064f955de7a843e96e2d7d3041c2) (may encounter 2 failures)
* Ruby 2.1.9 - [Suite](https://github.com/ruby/spec/commit/f029e65241374386077ac500add557ae65069b55) using [MSpec](https://github.com/ruby/mspec/commit/55568ea3918c6380e64db8c567d732fa5781efed)
### Running the specs
First, clone this repository:

View File

@ -17,9 +17,12 @@ describe "The -e command line option" do
ruby_exe("puts __FILE__", escape: false).chomp.should == "-e"
end
it "uses '-e' in $0" do
system(*ruby_exe, '-e', 'exit $0 == "-e"').should == true
end
#needs to test return => LocalJumpError
quarantine! do # For some unknown reason, running these under `bundle exec` or with -rbundler/setup fails
describe "with -n and a Fixnum range" do
before :each do
@script = "-ne 'print if %s' #{fixture(__FILE__, "conditional_range.txt")}"
@ -36,4 +39,3 @@ quarantine! do # For some unknown reason, running these under `bundle exec` or w
end
end
end
end

View File

@ -3,4 +3,11 @@ require File.expand_path('../shared/verbose', __FILE__)
describe "The -v command line option" do
it_behaves_like :command_line_verbose, "-v"
describe "when used alone" do
it "prints version and ends" do
version = ruby_exe(nil, args: '--version')
ruby_exe(nil, args: '-v').should == version
end
end
end

View File

@ -15,7 +15,7 @@ describe "Kernel#exit!" do
Kernel.should have_private_instance_method(:exit!)
end
it_behaves_like :process_exit!, :exit!, KernelSpecs::Method.new
it_behaves_like :process_exit!, :exit!, "self"
end
describe "Kernel.exit" do

View File

@ -342,4 +342,20 @@ describe "Module#prepend" do
child_class.new.foo(ary)
ary.should == [3, 2, 1]
end
describe "called on a module" do
describe "included into a class"
it "does not obscure the module's methods from reflective access" do
mod = Module.new do
def foo; end
end
cls = Class.new do
include mod
end
pre = Module.new
mod.prepend pre
cls.instance_methods.should include(:foo)
end
end
end

View File

@ -0,0 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Random::DEFAULT" do
it "returns a Random instance" do
Random::DEFAULT.should be_an_instance_of(Random)
end
end

View File

@ -7,4 +7,14 @@ describe "Rational#to_r" do
obj = BasicObject.new
lambda { Rational(obj) }.should raise_error(TypeError)
end
it "works when a BasicObject has to_r" do
obj = BasicObject.new; def obj.to_r; 1 / 2.to_r end
Rational(obj).should == Rational('1/2')
end
it "fails when a BasicObject's to_r does not return a Rational" do
obj = BasicObject.new; def obj.to_r; 1 end
lambda { Rational(obj) }.should raise_error(TypeError)
end
end

View File

@ -6,12 +6,9 @@ describe "Struct#inspect" do
it "returns a string representation of some kind" do
car = StructClasses::Car.new('Ford', 'Ranger')
car.inspect.should == '#<struct StructClasses::Car make="Ford", model="Ranger", year=nil>'
# ujihisa reported in http://rubyspec.org/issues/show/130 that the
# following example failed under mspec. Prefixing 'Whiskey' with a double
# colon causes it to work. Given that this is an mspec bug, as opposed to
# a problem with a spec, I've used the workaround below.
::Whiskey = Struct.new(:name, :ounces)
::Whiskey.new('Jack', 100).inspect.should == '#<struct Whiskey name="Jack", ounces=100>'
Whiskey = Struct.new(:name, :ounces)
Whiskey.new('Jack', 100).inspect.should == '#<struct Whiskey name="Jack", ounces=100>'
end
it_behaves_like(:struct_inspect, :inspect)

View File

@ -41,4 +41,20 @@ describe "Thread#status" do
it "reports aborting on a killed thread after sleep" do
ThreadSpecs.status_of_dying_thread_after_sleep.status.should == 'aborting'
end
it "reports aborting on an externally killed thread that sleeps" do
q = Queue.new
t = Thread.new do
begin
q.push nil
sleep
ensure
q.push Thread.current.status
end
end
q.pop
t.kill
t.join
q.pop.should == 'aborting'
end
end

View File

@ -5,7 +5,3 @@ require File.expand_path('../shared/exit', __FILE__)
describe "Thread#terminate" do
it_behaves_like :thread_exit, :terminate
end
describe "Thread#terminate!" do
it "needs to be reviewed for spec completeness"
end

View File

@ -24,6 +24,11 @@ describe :time_params, shared: true do
Time.send(@method, 2000, 2, 3, 4, 5, 0)
end
it "accepts a too big day of the month by going to the next month" do
Time.send(@method, 1999, 2, 31).should ==
Time.send(@method, 1999, 3, 3)
end
it "raises a TypeError if the year is nil" do
lambda { Time.send(@method, nil) }.should raise_error(TypeError)
end

View File

@ -12,6 +12,12 @@ describe "The for expression" do
j.should == 6
end
it "iterates over a list of arrays and destructures with empty comma" do
for i, in [[1,2]]
i.should == 1
end
end
it "iterates over an Hash passing each key-value pair to the block" do
k = 0
l = 0

View File

@ -53,9 +53,12 @@ describe :getoptlong_get, shared: true do
end
end
it "returns multiline argument" do
argv [ "--size=\n10k\n" ] do
@opts.send(@method).should == [ "--size", "\n10k\n" ]
ruby_version_is "2.5" do
# https://bugs.ruby-lang.org/issues/13858
it "returns multiline argument" do
argv [ "--size=\n10k\n" ] do
@opts.send(@method).should == [ "--size", "\n10k\n" ]
end
end
end
end

View File

@ -6,6 +6,13 @@ describe "Net::HTTP#send_request" do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
# HEAD is special so handled separately
@methods = %w[
GET POST PUT DELETE
OPTIONS
PROPFIND PROPPATCH LOCK UNLOCK
]
end
after :each do
@ -16,103 +23,39 @@ describe "Net::HTTP#send_request" do
# TODO: Does only work with GET and POST requests
describe "when passed type, path" do
it "sends a HTTP Request of the passed type to the passed path" do
response = @http.send_request("GET", "/request")
response.body.should == "Request type: GET"
response = @http.send_request("HEAD", "/request")
response.body.should be_nil
# response = @http.send_request("HEAD", "/request")
# response.body.should be_nil
response = @http.send_request("POST", "/request")
response.body.should == "Request type: POST"
# response = @http.send_request("PUT", "/request")
# response.body.should == "Request type: PUT"
# response = @http.send_request("DELETE", "/request")
# response.body.should == "Request type: DELETE"
# response = @http.send_request("PROPGET", "/request")
# response.body.should == "Request type: DELETE"
# response = @http.send_request("PROPSET", "/request")
# response.body.should == "Request type: DELETE"
# response = @http.send_request("OPTIONS", "/request")
# response.body.should be_nil
# response = @http.send_request("LOCK", "/request")
# response.body.should == "Request type: LOCK
# response = @http.send_request("UNLOCK", "/request")
# response.body.should == "Request type: UNLOCK
@methods.each do |method|
response = @http.send_request(method, "/request")
response.body.should == "Request type: #{method}"
end
end
end
describe "when passed type, path, body" do
it "sends a HTTP Request with the passed body" do
response = @http.send_request("GET", "/request/body", "test=test")
response.body.should == "test=test"
response = @http.send_request("HEAD", "/request/body", "test=test")
response.body.should be_nil
# response = @http.send_request("HEAD", "/request/body", "test=test")
# response.body.should be_nil
response = @http.send_request("POST", "/request/body", "test=test")
response.body.should == "test=test"
# response = @http.send_request("PUT", "/request/body", "test=test")
# response.body.should == "test=test"
# response = @http.send_request("DELETE", "/request/body", "test=test")
# response.body.should == "test=test"
# response = @http.send_request("PROPGET", "/request/body", "test=test")
# response.body.should == "test=test"
# response = @http.send_request("PROPSET", "/request/body", "test=test")
# response.body.should == "test=test"
# response = @http.send_request("OPTIONS", "/request/body", "test=test")
# response.body.should be_nil
# response = @http.send_request("LOCK", "/request/body", "test=test")
# response.body.should == "test=test"
# response = @http.send_request("UNLOCK", "/request/body", "test=test")
# response.body.should == "test=test"
@methods.each do |method|
response = @http.send_request(method, "/request/body", "test=test")
response.body.should == "test=test"
end
end
end
describe "when passed type, path, body, headers" do
it "sends a HTTP Request with the passed headers" do
response = @http.send_request("GET", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
response.body.should include('"referer"=>["http://www.rubyspec.org"]')
referer = 'https://www.ruby-lang.org/'.freeze
# response = @http.send_request("HEAD", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should be_nil
response = @http.send_request("HEAD", "/request/header", "test=test", "referer" => referer)
response.body.should be_nil
response = @http.send_request("POST", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
response.body.should include('"referer"=>["http://www.rubyspec.org"]')
# response = @http.send_request("PUT", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should include('"referer"=>["http://www.rubyspec.org"]')
# response = @http.send_request("DELETE", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should include('"referer"=>["http://www.rubyspec.org"]')
# response = @http.send_request("PROPGET", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should include('"referer"=>["http://www.rubyspec.org"]')
# response = @http.send_request("PROPSET", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should include('"referer"=>["http://www.rubyspec.org"]')
# response = @http.send_request("OPTIONS", "/request/body", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should be_nil
# response = @http.send_request("LOCK", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should include('"referer"=>["http://www.rubyspec.org"]')
# response = @http.send_request("UNLOCK", "/request/header", "test=test", "referer" => "http://www.rubyspec.org")
# response.body.should include('"referer"=>["http://www.rubyspec.org"]')
@methods.each do |method|
response = @http.send_request(method, "/request/header", "test=test", "referer" => referer)
response.body.should include('"referer"=>["' + referer + '"]')
end
end
end
end

View File

@ -5,23 +5,37 @@
extern "C" {
#endif
static VALUE fixnum_spec_FIX2INT(VALUE self, VALUE value) {
int i = FIX2INT(value);
return INT2NUM(i);
}
static VALUE fixnum_spec_FIX2UINT(VALUE self, VALUE value) {
unsigned int i = FIX2UINT(value);
return UINT2NUM(i);
}
#ifdef HAVE_RB_FIX2UINT
static VALUE fixnum_spec_rb_fix2uint(VALUE self, VALUE value) {
return INT2FIX(rb_fix2uint(value));
unsigned int i = rb_fix2uint(value);
return UINT2NUM(i);
}
#endif
#ifdef HAVE_RB_FIX2INT
static VALUE fixnum_spec_rb_fix2int(VALUE self, VALUE value) {
return INT2FIX(rb_fix2int(value));
int i = rb_fix2int(value);
return INT2NUM(i);
}
#endif
void Init_fixnum_spec(void) {
VALUE cls;
cls = rb_define_class("CApiFixnumSpecs", rb_cObject);
rb_define_method(cls, "FIX2INT", fixnum_spec_FIX2INT, 1);
rb_define_method(cls, "FIX2UINT", fixnum_spec_FIX2UINT, 1);
#ifdef HAVE_RB_FIX2UINT
rb_define_method(cls, "rb_fix2uint", fixnum_spec_rb_fix2uint, 1);
#endif

View File

@ -30,6 +30,13 @@ static VALUE gc_spec_rb_gc_disable() {
}
#endif
#ifdef HAVE_RB_GC
static VALUE gc_spec_rb_gc() {
rb_gc();
return Qnil;
}
#endif
void Init_gc_spec(void) {
VALUE cls;
@ -54,6 +61,10 @@ void Init_gc_spec(void) {
rb_define_method(cls, "rb_gc_disable", gc_spec_rb_gc_disable, 0);
#endif
#ifdef HAVE_RB_GC
rb_define_method(cls, "rb_gc", gc_spec_rb_gc, 0);
#endif
}
#ifdef __cplusplus

View File

@ -23,6 +23,12 @@ VALUE hash_spec_rb_hash_dup(VALUE self, VALUE hash) {
}
#endif
#ifdef HAVE_RB_HASH_FETCH
VALUE hash_spec_rb_hash_fetch(VALUE self, VALUE hash, VALUE key) {
return rb_hash_fetch(hash, key);
}
#endif
#ifdef HAVE_RB_HASH_FREEZE
VALUE hash_spec_rb_hash_freeze(VALUE self, VALUE hash) {
return rb_hash_freeze(hash);
@ -175,6 +181,10 @@ void Init_hash_spec(void) {
rb_define_method(cls, "rb_hash_delete_if", hash_spec_rb_hash_delete_if, 1);
#endif
#ifdef HAVE_RB_HASH_FETCH
rb_define_method(cls, "rb_hash_fetch", hash_spec_rb_hash_fetch, 2);
#endif
#ifdef HAVE_RB_HASH_FOREACH
rb_define_method(cls, "rb_hash_foreach", hash_spec_rb_hash_foreach, 1);
rb_define_method(cls, "rb_hash_foreach_stop", hash_spec_rb_hash_foreach_stop, 1);

View File

@ -17,6 +17,18 @@ VALUE proc_spec_rb_proc_new(VALUE self) {
}
#endif
#ifdef HAVE_RB_PROC_ARITY
VALUE proc_spec_rb_proc_arity(VALUE self, VALUE prc) {
return INT2FIX(rb_proc_arity(prc));
}
#endif
#ifdef HAVE_RB_PROC_CALL
VALUE proc_spec_rb_proc_call(VALUE self, VALUE prc, VALUE args) {
return rb_proc_call(prc, args);
}
#endif
/* This helper is not strictly necessary but reflects the code in wxRuby that
* originally exposed issues with this Proc.new behavior.
*/
@ -57,6 +69,14 @@ void Init_proc_spec(void) {
rb_define_method(cls, "rb_proc_new", proc_spec_rb_proc_new, 0);
#endif
#ifdef HAVE_RB_PROC_ARITY
rb_define_method(cls, "rb_proc_arity", proc_spec_rb_proc_arity, 1);
#endif
#ifdef HAVE_RB_PROC_CALL
rb_define_method(cls, "rb_proc_call", proc_spec_rb_proc_call, 2);
#endif
rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1);
}

View File

@ -29,6 +29,21 @@ VALUE range_spec_rb_range_values(VALUE self, VALUE range) {
}
#endif
#ifdef HAVE_RB_RANGE_BEG_LEN
VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE begpv, VALUE lenpv, VALUE lenv, VALUE errv) {
long begp = FIX2LONG(begpv);
long lenp = FIX2LONG(lenpv);
long len = FIX2LONG(lenv);
long err = FIX2LONG(errv);
VALUE ary = rb_ary_new();
VALUE res = rb_range_beg_len(range, &begp, &lenp, len, err);
rb_ary_store(ary, 0, LONG2FIX(begp));
rb_ary_store(ary, 1, LONG2FIX(lenp));
rb_ary_store(ary, 2, res);
return ary;
}
#endif
void Init_range_spec(void) {
VALUE cls;
cls = rb_define_class("CApiRangeSpecs", rb_cObject);
@ -40,6 +55,10 @@ void Init_range_spec(void) {
#ifdef HAVE_RB_RANGE_VALUES
rb_define_method(cls, "rb_range_values", range_spec_rb_range_values, 1);
#endif
#ifdef HAVE_RB_RANGE_BEG_LEN
rb_define_method(cls, "rb_range_beg_len", range_spec_rb_range_beg_len, 5);
#endif
}
#ifdef __cplusplus

View File

@ -299,6 +299,7 @@
#define HAVE_RB_HASH_CLEAR 1
#define HAVE_RB_HASH_DELETE 1
#define HAVE_RB_HASH_DELETE_IF 1
#define HAVE_RB_HASH_FETCH 1
#define HAVE_RB_HASH_FOREACH 1
#define HAVE_RB_HASH_LOOKUP 1
#define HAVE_RB_HASH_LOOKUP2 1
@ -372,6 +373,7 @@
#define HAVE_RB_GC_REGISTER_ADDRESS 1
#define HAVE_RB_GC_ENABLE 1
#define HAVE_RB_GC_DISABLE 1
#define HAVE_RB_GC 1
/* Marshal */
#define HAVE_RB_MARSHAL_DUMP 1
@ -476,10 +478,13 @@
/* Proc */
#define HAVE_RB_PROC_NEW 1
#define HAVE_RB_PROC_ARITY 1
#define HAVE_RB_PROC_CALL 1
/* Range */
#define HAVE_RB_RANGE_NEW 1
#define HAVE_RB_RANGE_VALUES 1
#define HAVE_RB_RANGE_BEG_LEN 1
/* Rational */
#define HAVE_RB_RATIONAL 1
@ -499,6 +504,9 @@
#define HAVE_RB_REG_OPTIONS 1
#define HAVE_RB_REG_REGCOMP 1
/* st */
#define HAVE_RB_ST 1
/* String */
#define HAVE_RB_CSTR2INUM 1
#define HAVE_RB_CSTR_TO_INUM 1
@ -522,6 +530,8 @@
#define HAVE_RB_STR_NEW3 1
#define HAVE_RB_STR_NEW4 1
#define HAVE_RB_STR_NEW5 1
#define HAVE_RB_TAINTED_STR_NEW 1
#define HAVE_RB_TAINTED_STR_NEW2 1
#define HAVE_RB_STR_PLUS 1
#define HAVE_RB_STR_TIMES 1
#define HAVE_RB_STR_RESIZE 1

View File

@ -0,0 +1,82 @@
#include "ruby.h"
#include "rubyspec.h"
#include <string.h>
#include <stdarg.h>
#ifdef HAVE_RB_ST
#include <ruby/st.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HAVE_RB_ST
VALUE st_spec_st_init_numtable(VALUE self) {
st_table *tbl = st_init_numtable();
int entries = tbl->num_entries;
st_free_table(tbl);
return INT2FIX(entries);
}
VALUE st_spec_st_init_numtable_with_size(VALUE self) {
st_table *tbl = st_init_numtable_with_size(128);
int entries = tbl->num_entries;
st_free_table(tbl);
return INT2FIX(entries);
}
VALUE st_spec_st_insert(VALUE self) {
int entries;
st_table *tbl = st_init_numtable_with_size(128);
st_insert(tbl, 1, 1);
entries = tbl->num_entries;
st_free_table(tbl);
return INT2FIX(entries);
}
static int sum(st_data_t key, st_data_t value, st_data_t arg) {
*(int*)arg += value;
return ST_CONTINUE;
}
VALUE st_spec_st_foreach(VALUE self) {
int total = 0;
st_table *tbl = st_init_numtable_with_size(128);
st_insert(tbl, 1, 3);
st_insert(tbl, 2, 4);
st_foreach(tbl, sum, (st_data_t)&total);
st_free_table(tbl);
return INT2FIX(total);
}
VALUE st_spec_st_lookup(VALUE self) {
st_data_t result = (st_data_t)0;
st_table *tbl = st_init_numtable_with_size(128);
st_insert(tbl, 7, 42);
st_insert(tbl, 2, 4);
st_lookup(tbl, (st_data_t)7, &result);
st_free_table(tbl);
return INT2FIX(result);
}
#endif
void Init_st_spec(void) {
VALUE cls;
cls = rb_define_class("CApiStSpecs", rb_cObject);
#ifdef HAVE_RB_ST
rb_define_method(cls, "st_init_numtable", st_spec_st_init_numtable, 0);
rb_define_method(cls, "st_init_numtable_with_size", st_spec_st_init_numtable_with_size, 0);
rb_define_method(cls, "st_insert", st_spec_st_insert, 0);
rb_define_method(cls, "st_foreach", st_spec_st_foreach, 0);
rb_define_method(cls, "st_lookup", st_spec_st_lookup, 0);
#endif
}
#ifdef __cplusplus
}
#endif

View File

@ -257,6 +257,18 @@ VALUE string_spec_rb_str_new5(VALUE self, VALUE str, VALUE ptr, VALUE len) {
}
#endif
#ifdef HAVE_RB_TAINTED_STR_NEW
VALUE string_spec_rb_tainted_str_new(VALUE self, VALUE str, VALUE len) {
return rb_tainted_str_new(RSTRING_PTR(str), FIX2INT(len));
}
#endif
#ifdef HAVE_RB_TAINTED_STR_NEW2
VALUE string_spec_rb_tainted_str_new2(VALUE self, VALUE str) {
return rb_tainted_str_new2(RSTRING_PTR(str));
}
#endif
#ifdef HAVE_RB_STR_PLUS
VALUE string_spec_rb_str_plus(VALUE self, VALUE str1, VALUE str2) {
return rb_str_plus(str1, str2);
@ -564,6 +576,14 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_str_new5", string_spec_rb_str_new5, 3);
#endif
#ifdef HAVE_RB_TAINTED_STR_NEW
rb_define_method(cls, "rb_tainted_str_new", string_spec_rb_tainted_str_new, 2);
#endif
#ifdef HAVE_RB_TAINTED_STR_NEW2
rb_define_method(cls, "rb_tainted_str_new2", string_spec_rb_tainted_str_new2, 1);
#endif
#ifdef HAVE_RB_STR_PLUS
rb_define_method(cls, "rb_str_plus", string_spec_rb_str_plus, 2);
#endif

View File

@ -7,6 +7,40 @@ describe "CApiFixnumSpecs" do
@s = CApiFixnumSpecs.new
end
describe "FIX2INT" do
it "converts a Fixnum to a native int" do
@s.FIX2INT(42).should == 42
@s.FIX2INT(-14).should == -14
end
max_int = (1 << 31) - 1
min_int = -(1 << 31)
guard -> { fixnum_min <= min_int and max_int <= fixnum_max } do
it "converts a Fixnum representing the minimum and maximum native int" do
@s.FIX2INT(max_int).should == max_int
@s.FIX2INT(min_int).should == min_int
end
end
end
describe "FIX2UINT" do
it "converts a Fixnum to a native int" do
@s.FIX2UINT(42).should == 42
@s.FIX2UINT(0).should == 0
end
max_uint = (1 << 32) - 1
guard -> { max_uint <= fixnum_max } do
it "converts a Fixnum representing the maximum native uint" do
@s.FIX2UINT(max_uint).should == max_uint
end
end
end
platform_is wordsize: 64 do
describe "rb_fix2uint" do
it "raises a TypeError if passed nil" do
@ -14,6 +48,7 @@ describe "CApiFixnumSpecs" do
end
it "converts a Fixnum" do
@s.rb_fix2uint(0).should == 0
@s.rb_fix2uint(1).should == 1
end
@ -25,6 +60,12 @@ describe "CApiFixnumSpecs" do
@s.rb_fix2uint(25.4567).should == 25
end
it "raises a RangeError if the value does not fit a native uint" do
# Interestingly, on MRI rb_fix2uint(-1) is allowed
lambda { @s.rb_fix2uint(0xffff_ffff+1) }.should raise_error(RangeError)
lambda { @s.rb_fix2uint(-(1 << 31) - 1) }.should raise_error(RangeError)
end
it "raises a RangeError if the value is more than 32bits" do
lambda { @s.rb_fix2uint(0xffff_ffff+1) }.should raise_error(RangeError)
end
@ -44,7 +85,11 @@ describe "CApiFixnumSpecs" do
@s.rb_fix2int(1).should == 1
end
it "converts the maximum uint value" do
it "converts the minimum int value" do
@s.rb_fix2int(-(1 << 31)).should == -(1 << 31)
end
it "converts the maximum int value" do
@s.rb_fix2int(0x7fff_ffff).should == 0x7fff_ffff
end
@ -56,6 +101,11 @@ describe "CApiFixnumSpecs" do
@s.rb_fix2int(-2147442171).should == -2147442171
end
it "raises a RangeError if the value does not fit a native int" do
lambda { @s.rb_fix2int(0x7fff_ffff+1) }.should raise_error(RangeError)
lambda { @s.rb_fix2int(-(1 << 31) - 1) }.should raise_error(RangeError)
end
it "raises a RangeError if the value is more than 32bits" do
lambda { @s.rb_fix2int(0xffff_ffff+1) }.should raise_error(RangeError)
end

View File

@ -41,4 +41,14 @@ describe "CApiGCSpecs" do
end
end
describe "rb_gc" do
it "increases gc count" do
gc_count = GC.count
@f.rb_gc
GC.count.should > gc_count
end
end
end

View File

@ -119,6 +119,25 @@ describe "C-API Hash function" do
end
end
describe "rb_hash_fetch" do
before :each do
@hsh = {:a => 1, :b => 2}
end
it "returns the value associated with the key" do
@s.rb_hash_fetch(@hsh, :b).should == 2
end
it "raises a KeyError if the key is not found and default is set" do
@hsh.default = :d
lambda { @s.rb_hash_fetch(@hsh, :c) }.should raise_error(KeyError)
end
it "raises a KeyError if the key is not found and no default is set" do
lambda { @s.rb_hash_fetch(@hsh, :c) }.should raise_error(KeyError)
end
end
describe "rb_hash_foreach" do
it "iterates over the hash" do
hsh = {name: "Evan", sign: :libra}

View File

@ -40,6 +40,20 @@ describe "C-API Proc function" do
@prc.source_location.should == nil
end
end
describe "rb_proc_arity" do
it "returns the correct arity" do
prc = Proc.new {|a,b,c|}
@p.rb_proc_arity(prc).should == 3
end
end
describe "rb_proc_call" do
it "calls the Proc" do
prc = Proc.new {|a,b| a * b }
@p.rb_proc_call(prc, [6, 7]).should == 42
end
end
end
describe "C-API when calling Proc.new from a C function" do

View File

@ -65,4 +65,31 @@ describe "C-API Range function" do
excl.should be_false
end
end
describe "rb_range_beg_len" do
it "returns correct begin, length and result" do
r = 2..5
begp, lenp, result = @s.rb_range_beg_len(r, 0, 0, 10, 0)
result.should be_true
begp.should == 2
lenp.should == 4
end
it "returns nil when not in range" do
r = 2..5
begp, lenp, result = @s.rb_range_beg_len(r, 0, 0, 1, 0)
result.should be_nil
end
it "raises a RangeError when not in range and err is 1" do
r = -5..-1
lambda { @s.rb_range_beg_len(r, 0, 0, 1, 1) }.should raise_error(RangeError)
end
it "returns nil when not in range and err is 0" do
r = -5..-1
begp, lenp, result = @s.rb_range_beg_len(r, 0, 0, 1, 0)
result.should be_nil
end
end
end

View File

@ -0,0 +1,41 @@
# encoding: utf-8
require File.expand_path('../spec_helper', __FILE__)
load_extension('st')
describe "st hash table function" do
before :each do
@s = CApiStSpecs.new
end
describe "st_init_numtable" do
it "initializes without error" do
@s.st_init_numtable.should == 0
end
end
describe "st_init_numtable_with_size" do
it "initializes without error" do
@s.st_init_numtable_with_size.should == 0
end
end
describe "st_insert" do
it "returns size 1 after insert" do
@s.st_insert.should == 1
end
end
describe "st_foreach" do
it "iterates over each pair of key and value" do
@s.st_foreach.should == 7
end
end
describe "st_lookup" do
it "returns the expected value" do
@s.st_lookup.should == 42
end
end
end

View File

@ -228,6 +228,22 @@ describe "C-API String function" do
end
end
describe "rb_tainted_str_new" do
it "creates a new tainted String" do
newstring = @s.rb_tainted_str_new("test", 4)
newstring.should == "test"
newstring.tainted?.should be_true
end
end
describe "rb_tainted_str_new2" do
it "creates a new tainted String" do
newstring = @s.rb_tainted_str_new2("test")
newstring.should == "test"
newstring.tainted?.should be_true
end
end
describe "rb_str_append" do
it "appends a string to another string" do
@s.rb_str_append("Hello", " Goodbye").should == "Hello Goodbye"

View File

@ -74,23 +74,21 @@ describe :process_exit, shared: true do
end
describe :process_exit!, shared: true do
with_feature :fork do
it "exits with the given status" do
pid = Process.fork { @object.exit!(1) }
pid, status = Process.waitpid2(pid)
status.exitstatus.should == 1
end
it "exits with the given status" do
out = ruby_exe("#{@object}.send(:exit!, 21)", args: '2>&1')
out.should == ""
$?.exitstatus.should == 21
end
it "exits when called from a thread" do
pid = Process.fork do
Thread.new { @object.exit!(1) }.join
it "exits when called from a thread" do
out = ruby_exe("Thread.new { #{@object}.send(:exit!, 21) }.join; sleep", args: '2>&1')
out.should == ""
$?.exitstatus.should == 21
end
# Do not let the main thread complete
sleep
end
pid, status = Process.waitpid2(pid)
status.exitstatus.should == 1
end
it "exits when called from a fiber" do
out = ruby_exe("Fiber.new { #{@object}.send(:exit!, 21) }.resume", args: '2>&1')
out.should == ""
$?.exitstatus.should == 21
end
end