1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
This commit is contained in:
Benoit Daloze 2020-06-27 15:51:37 +02:00
parent 64d8c0815e
commit b3fa158d1c
35 changed files with 652 additions and 56 deletions

View file

@ -15,6 +15,10 @@ Layout/TrailingEmptyLines:
Exclude:
- library/coverage/fixtures/some_class.rb
Layout/SpaceInLambdaLiteral:
Enabled: true
EnforcedStyle: require_space
Lint:
Enabled: true

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash
exec somehow this file
echo 'error' && exit 1
#!ruby
puts 'success'

View file

@ -323,6 +323,10 @@ describe "Array#[]= with [index, count]" do
b = [1, 2, 3, 4, 5]
b[10, 0] = [1]
a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 1]
c = [1, 2, 3, 4, 5]
c[10, 0] = []
c.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil]
end
it "inserts other section in place defined by idx" do

View file

@ -0,0 +1,22 @@
require_relative '../../spec_helper'
describe "An Exception reaching the top level" do
it "is printed on STDERR" do
ruby_exe('raise "foo"', args: "2>&1").should.include?("in `<main>': foo (RuntimeError)")
end
describe "with a custom backtrace" do
it "is printed on STDERR" do
code = <<-RUBY
raise RuntimeError, "foo", [
"/dir/foo.rb:10:in `raising'",
"/dir/bar.rb:20:in `caller'",
]
RUBY
ruby_exe(code, args: "2>&1").should == <<-EOS
/dir/foo.rb:10:in `raising': foo (RuntimeError)
\tfrom /dir/bar.rb:20:in `caller'
EOS
end
end
end

View file

@ -43,5 +43,9 @@ describe "Integer#pow" do
it "raises a ZeroDivisionError when the given argument is 0" do
-> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError)
end
it "raises a RangeError when the first argument is negative and the second argument is present" do
-> { 2.pow(-5, 1) }.should raise_error(RangeError)
end
end
end

View file

@ -66,6 +66,10 @@ describe "IO#ungetbyte" do
end
end
it "raises IOError on stream not opened for reading" do
-> { STDOUT.ungetbyte(42) }.should raise_error(IOError, "not opened for reading")
end
it "raises an IOError if the IO is closed" do
@io.close
-> { @io.ungetbyte(42) }.should raise_error(IOError)

View file

@ -136,6 +136,10 @@ describe "IO#ungetc" do
@io.ungetc(100).should be_nil
end
it "raises IOError on stream not opened for reading" do
-> { STDOUT.ungetc(100) }.should raise_error(IOError, "not opened for reading")
end
it "raises IOError on closed stream" do
@io.getc
@io.close

View file

@ -0,0 +1,29 @@
require_relative '../../spec_helper'
describe "Kernel#initialize_copy" do
it "does nothing if the argument is the same as the receiver" do
obj = Object.new
obj.send(:initialize_copy, obj).should.equal?(obj)
obj.freeze
obj.send(:initialize_copy, obj).should.equal?(obj)
1.send(:initialize_copy, 1).should.equal?(1)
end
it "raises FrozenError if the receiver is frozen" do
-> { Object.new.freeze.send(:initialize_copy, Object.new) }.should raise_error(FrozenError)
-> { 1.send(:initialize_copy, Object.new) }.should raise_error(FrozenError)
end
it "raises TypeError if the objects are of different class" do
klass = Class.new
sub = Class.new(klass)
a = klass.new
b = sub.new
message = 'initialize_copy should take same class object'
-> { a.send(:initialize_copy, b) }.should raise_error(TypeError, message)
-> { b.send(:initialize_copy, a) }.should raise_error(TypeError, message)
-> { a.send(:initialize_copy, 1) }.should raise_error(TypeError, message)
-> { a.send(:initialize_copy, 1.0) }.should raise_error(TypeError, message)
end
end

View file

@ -36,27 +36,31 @@ describe "Kernel.proc" do
end
describe "Kernel#proc" do
def some_method
proc
end
ruby_version_is ""..."2.7" do
it "uses the implicit block from an enclosing method" do
def some_method
proc
end
prc = some_method { "hello" }
prc.call.should == "hello"
end
end
ruby_version_is "2.7" ... "2.8" do
ruby_version_is "2.7"..."2.8" do
it "can be created when called with no block" do
def some_method
proc
end
-> {
some_method { "hello" }
}.should complain(/Capturing the given block using Kernel#proc is deprecated/)
end
end
ruby_version_is "2.8" do
it "raises an ArgumentError when passed no block" do
-> {
some_method { "hello" }
}.should raise_error(ArgumentError, 'tried to create Proc object without a block')
end
end
end

View file

@ -11,6 +11,10 @@ describe "Kernel.srand" do
srand(20).should == 10
end
it "returns the previous seed value on the first call" do
ruby_exe('p srand(10)', options: '--disable-gems').chomp.should =~ /\A\d+\z/
end
it "seeds the RNG correctly and repeatably" do
srand(10)
x = rand

View file

@ -10,4 +10,8 @@ module ModuleSpecs
module IncludedModule
def foo; "foo from included module"; end
end
def self.build_refined_class
Class.new(ClassWithFoo)
end
end

View file

@ -87,6 +87,31 @@ describe "Module#refine" do
inner_self.public_instance_methods.should include(:blah)
end
it "applies refinements to the module" do
refinement = Module.new do
refine(Enumerable) do
def foo?
self.any? ? "yes" : "no"
end
end
end
foo = Class.new do
using refinement
def initialize(items)
@items = items
end
def result
@items.foo?
end
end
foo.new([]).result.should == "no"
foo.new([1]).result.should == "yes"
end
it "raises ArgumentError if not given a block" do
-> do
Module.new do
@ -196,8 +221,10 @@ describe "Module#refine" do
# * The included modules of C
describe "method lookup" do
it "looks in the object singleton class first" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo; "foo from refinement"; end
end
end
@ -206,7 +233,7 @@ describe "Module#refine" do
Module.new do
using refinement
obj = ModuleSpecs::ClassWithFoo.new
obj = refined_class.new
class << obj
def foo; "foo from singleton class"; end
end
@ -216,9 +243,66 @@ describe "Module#refine" do
result.should == "foo from singleton class"
end
it "looks in prepended modules from the refinement first" do
it "looks in the included modules for builtin methods" do
result = ruby_exe(<<-RUBY)
a = Module.new do
def /(other) quo(other) end
end
refinement = Module.new do
refine Integer do
include a
end
end
result = nil
Module.new do
using refinement
result = 1 / 2
end
print result.class
RUBY
result.should == 'Rational'
end
it "looks in later included modules of the refined module first" do
a = Module.new do
def foo
"foo from A"
end
end
include_me_later = Module.new do
def foo
"foo from IncludeMeLater"
end
end
c = Class.new do
include a
end
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine c do; end
end
result = nil
Module.new do
using refinement
c.include include_me_later
result = c.new.foo
end
result.should == "foo from IncludeMeLater"
end
it "looks in prepended modules from the refinement first" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine refined_class do
include ModuleSpecs::IncludedModule
prepend ModuleSpecs::PrependedModule
@ -229,15 +313,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.foo
result = refined_class.new.foo
end
result.should == "foo from prepended module"
end
it "looks in refinement then" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine(ModuleSpecs::ClassWithFoo) do
refine(refined_class) do
include ModuleSpecs::IncludedModule
def foo; "foo from refinement"; end
@ -247,15 +333,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.foo
result = refined_class.new.foo
end
result.should == "foo from refinement"
end
it "looks in included modules from the refinement then" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
include ModuleSpecs::IncludedModule
end
end
@ -263,21 +351,23 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.foo
result = refined_class.new.foo
end
result.should == "foo from included module"
end
it "looks in the class then" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine(ModuleSpecs::ClassWithFoo) { }
refine(refined_class) { }
end
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.foo
result = refined_class.new.foo
end
result.should == "foo"
@ -287,12 +377,14 @@ describe "Module#refine" do
# methods in a subclass have priority over refinements in a superclass
it "does not override methods in subclasses" do
subclass = Class.new(ModuleSpecs::ClassWithFoo) do
refined_class = ModuleSpecs.build_refined_class
subclass = Class.new(refined_class) do
def foo; "foo from subclass"; end
end
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo; "foo from refinement"; end
end
end
@ -308,8 +400,10 @@ describe "Module#refine" do
context "for methods accessed indirectly" do
it "is honored by Kernel#send" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo; "foo from refinement"; end
end
end
@ -317,15 +411,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.send :foo
result = refined_class.new.send :foo
end
result.should == "foo from refinement"
end
it "is honored by BasicObject#__send__" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo; "foo from refinement"; end
end
end
@ -333,7 +429,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.__send__ :foo
result = refined_class.new.__send__ :foo
end
result.should == "foo from refinement"
@ -359,8 +455,10 @@ describe "Module#refine" do
ruby_version_is "" ... "2.6" do
it "is not honored by Kernel#public_send" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo; "foo from refinement"; end
end
end
@ -368,7 +466,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.public_send :foo
result = refined_class.new.public_send :foo
end
result.should == "foo"
@ -377,8 +475,10 @@ describe "Module#refine" do
ruby_version_is "2.6" do
it "is honored by Kernel#public_send" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo; "foo from refinement"; end
end
end
@ -386,7 +486,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.public_send :foo
result = refined_class.new.public_send :foo
end
result.should == "foo from refinement"
@ -590,8 +690,10 @@ describe "Module#refine" do
context "when super is called in a refinement" do
it "looks in the included to refinery module" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
include ModuleSpecs::IncludedModule
def foo
@ -603,15 +705,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.foo
result = refined_class.new.foo
end
result.should == "foo from included module"
end
it "looks in the refined class" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo
super
end
@ -621,7 +725,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.foo
result = refined_class.new.foo
end
result.should == "foo"
@ -631,8 +735,10 @@ describe "Module#refine" do
# class even if there is another refinement which has been activated
# in the same context.
it "looks in the refined class even if there is another active refinement" do
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo
"foo from refinement"
end
@ -640,7 +746,7 @@ describe "Module#refine" do
end
refinement_with_super = Module.new do
refine ModuleSpecs::ClassWithFoo do
refine refined_class do
def foo
super
end
@ -651,7 +757,7 @@ describe "Module#refine" do
Module.new do
using refinement
using refinement_with_super
result = ModuleSpecs::ClassWithFoo.new.foo
result = refined_class.new.foo
end
result.should == "foo"

View file

@ -203,7 +203,7 @@ describe "Proc.new without a block" do
end
end
ruby_version_is "2.7" ... "2.8" do
ruby_version_is "2.7"..."2.8" do
it "can be created if invoked from within a method with a block" do
-> { ProcSpecs.new_proc_in_method { "hello" } }.should complain(/Capturing the given block using Proc.new is deprecated/)
end
@ -223,4 +223,16 @@ describe "Proc.new without a block" do
}.should complain(/Capturing the given block using Proc.new is deprecated/)
end
end
ruby_version_is "2.8" do
it "raises an ArgumentError when passed no block" do
def some_method
Proc.new
end
-> { ProcSpecs.new_proc_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
-> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
-> { some_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
end
end
end

View file

@ -57,7 +57,7 @@ describe "Proc#parameters" do
end
it "sets the first element of each sub-Array to :block for parameters prefixed with ampersands" do
->&x { }.parameters.first.first.should == :block
-> &x { }.parameters.first.first.should == :block
-> x, &y { }.parameters.last.first.should == :block
proc {|&x| }.parameters.first.first.should == :block
proc {|x,&y| }.parameters.last.first.should == :block
@ -68,7 +68,7 @@ describe "Proc#parameters" do
-> x=Math::PI { }.parameters.first.last.should == :x
-> an_argument, glark, &foo { }.parameters[1].last.should == :glark
-> *rest { }.parameters.first.last.should == :rest
->&block { }.parameters.first.last.should == :block
-> &block { }.parameters.first.last.should == :block
proc {|x| }.parameters.first.last.should == :x
proc {|x=Math::PI| }.parameters.first.last.should == :x
proc {|an_argument, glark, &foo| }.parameters[1].last.should == :glark

View file

@ -1,7 +1,7 @@
describe :proc_call_block_args, shared: true do
it "can receive block arguments" do
Proc.new {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2
->&b { b.send(@method)}.send(@method) {1 + 1}.should == 2
-> &b { b.send(@method)}.send(@method) {1 + 1}.should == 2
proc {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2
end

View file

@ -1,14 +1,19 @@
require_relative '../../spec_helper'
describe "Symbol.all_symbols" do
it "returns an array containing all the Symbols in the symbol table" do
it "returns an array of Symbols" do
all_symbols = Symbol.all_symbols
all_symbols.should be_an_instance_of(Array)
all_symbols.all? { |s| s.is_a?(Symbol) ? true : (p s; false) }.should == true
all_symbols.each { |s| s.should be_an_instance_of(Symbol) }
end
it "returns an Array containing Symbols that have been created" do
it "includes symbols that are strongly referenced" do
symbol = "symbol_specs_#{rand(5_000_000)}".to_sym
Symbol.all_symbols.should include(symbol)
end
it "includes symbols that are referenced in source code but not yet executed" do
Symbol.all_symbols.any? { |s| s.to_s == 'symbol_specs_referenced_in_source_code' }.should be_true
:symbol_specs_referenced_in_source_code
end
end

View file

@ -0,0 +1,107 @@
module RescueSpecs
class Captor
attr_accessor :captured_error
def self.should_capture_exception
captor = new
captor.capture('some text').should == :caught # Ensure rescue body still runs
captor.captured_error.message.should == 'some text'
end
end
class ClassVariableCaptor < Captor
def capture(msg)
raise msg
rescue => @@captured_error
:caught
end
def captured_error
self.class.remove_class_variable(:@@captured_error)
end
end
class ConstantCaptor < Captor
# Using lambda gets around the dynamic constant assignment warning
CAPTURE = -> msg {
begin
raise msg
rescue => CapturedError
:caught
end
}
def capture(msg)
CAPTURE.call(msg)
end
def captured_error
self.class.send(:remove_const, :CapturedError)
end
end
class GlobalVariableCaptor < Captor
def capture(msg)
raise msg
rescue => $captured_error
:caught
end
def captured_error
$captured_error.tap do
$captured_error = nil # Can't remove globals, only nil them out
end
end
end
class InstanceVariableCaptor < Captor
def capture(msg)
raise msg
rescue => @captured_error
:caught
end
end
class LocalVariableCaptor < Captor
def capture(msg)
raise msg
rescue => captured_error
@captured_error = captured_error
:caught
end
end
class SafeNavigationSetterCaptor < Captor
def capture(msg)
raise msg
rescue => self&.captured_error
:caught
end
end
class SetterCaptor < Captor
def capture(msg)
raise msg
rescue => self.captured_error
:caught
end
end
class SquareBracketsCaptor < Captor
def capture(msg)
@hash = {}
raise msg
rescue => self[:error]
:caught
end
def []=(key, value)
@hash[key] = value
end
def captured_error
@hash[:error]
end
end
end

View file

@ -156,6 +156,26 @@ describe "A method send" do
-> { m(1, 2, *x) }.should raise_error(TypeError)
end
end
context "with a block argument" do
before :all do
def m(x)
if block_given?
[true, yield(x + 'b')]
else
[false]
end
end
end
it "that refers to a proc passes the proc as the block" do
m('a', &-> y { y + 'c'}).should == [true, 'abc']
end
it "that is nil passes no block" do
m('a', &nil).should == [false]
end
end
end
describe "An element assignment method send" do

View file

@ -23,11 +23,41 @@ describe "The rescue keyword" do
end.should == :caught
end
it "can capture the raised exception in a local variable" do
begin
raise SpecificExampleException, "some text"
rescue SpecificExampleException => e
e.message.should == "some text"
describe 'can capture the raised exception' do
before :all do
require_relative 'fixtures/rescue_captures'
end
it 'in a local variable' do
RescueSpecs::LocalVariableCaptor.should_capture_exception
end
it 'in a class variable' do
RescueSpecs::ClassVariableCaptor.should_capture_exception
end
it 'in a constant' do
RescueSpecs::ConstantCaptor.should_capture_exception
end
it 'in a global variable' do
RescueSpecs::GlobalVariableCaptor.should_capture_exception
end
it 'in an instance variable' do
RescueSpecs::InstanceVariableCaptor.should_capture_exception
end
it 'using a safely navigated setter method' do
RescueSpecs::SafeNavigationSetterCaptor.should_capture_exception
end
it 'using a setter method' do
RescueSpecs::SetterCaptor.should_capture_exception
end
it 'using a square brackets setter' do
RescueSpecs::SquareBracketsCaptor.should_capture_exception
end
end

View file

@ -102,6 +102,37 @@ describe "The super keyword" do
c2.new.m(:dump) { :value }.should == :value
end
it "can pass an explicit block" do
c1 = Class.new do
def m(v)
yield(v)
end
end
c2 = Class.new(c1) do
def m(v)
block = -> w { yield(w + 'b') }
super(v, &block)
end
end
c2.new.m('a') { |x| x + 'c' }.should == 'abc'
end
it "can pass no block using &nil" do
c1 = Class.new do
def m(v)
block_given?
end
end
c2 = Class.new(c1) do
def m(v)
super(v, &nil)
end
end
c2.new.m('a') { raise }.should be_false
end
it "uses block argument given to method when used in a block" do
c1 = Class.new do
def m

View file

@ -28,8 +28,7 @@ describe 'RbConfig::CONFIG' do
ruby_exe(<<-RUBY, options: '--enable-frozen-string-literal').should == "Done\n"
require 'rbconfig'
RbConfig::CONFIG.each do |k, v|
# SDKROOT excluded here to workaround the issue: https://bugs.ruby-lang.org/issues/16738
if v.frozen? && k != 'SDKROOT'
if v.frozen?
puts "\#{k} Failure"
end
end

View file

@ -0,0 +1,11 @@
require_relative '../../spec_helper'
require 'stringio'
# This method is added by io/console on require.
describe "StringIO#getpass" do
require 'io/console'
it "is defined by io/console" do
StringIO.new("example").should.respond_to?(:getpass)
end
end

View file

@ -18,6 +18,22 @@ describe "Timeout.timeout" do
end.should raise_error(StandardError)
end
it "raises specified error type with specified message when it times out" do
-> do
Timeout.timeout(1, StandardError, "foobar") do
sleep
end
end.should raise_error(StandardError, "foobar")
end
it "raises specified error type with a default message when it times out if message is nil" do
-> do
Timeout.timeout(1, StandardError, nil) do
sleep
end
end.should raise_error(StandardError, "execution expired")
end
it "returns back the last value in the block" do
Timeout.timeout(1) do
42

View file

@ -190,6 +190,22 @@ describe "C-API Array function" do
end
end
describe "rb_ary_sort" do
it "returns a new sorted array" do
a = [2, 1, 3]
@s.rb_ary_sort(a).should == [1, 2, 3]
a.should == [2, 1, 3]
end
end
describe "rb_ary_sort_bang" do
it "sorts the given array" do
a = [2, 1, 3]
@s.rb_ary_sort_bang(a).should == [1, 2, 3]
a.should == [1, 2, 3]
end
end
describe "rb_ary_store" do
it "overwrites the element at the given position" do
a = [1, 2, 3]

View file

@ -82,12 +82,54 @@ describe "C-API Encoding function" do
end
end
describe "rb_enc_isalnum" do
it "returns non-zero for alpha-numeric characters" do
@s.rb_enc_isalnum("a".ord, Encoding::US_ASCII).should == true
@s.rb_enc_isalnum("2".ord, Encoding::US_ASCII).should == true
@s.rb_enc_isalnum("a".ord, Encoding::UTF_8).should == true
@s.rb_enc_isalnum("2".ord, Encoding::UTF_8).should == true
@s.rb_enc_isalnum("é".encode(Encoding::ISO_8859_1).ord, Encoding::ISO_8859_1).should == true
end
it "returns zero for non alpha-numeric characters" do
@s.rb_enc_isalnum("-".ord, Encoding::US_ASCII).should == false
@s.rb_enc_isalnum(" ".ord, Encoding::US_ASCII).should == false
@s.rb_enc_isalnum("-".ord, Encoding::UTF_8).should == false
@s.rb_enc_isalnum(" ".ord, Encoding::UTF_8).should == false
end
end
describe "rb_enc_isspace" do
it "returns non-zero for space characters" do
@s.rb_enc_isspace(" ".ord, Encoding::US_ASCII).should == true
@s.rb_enc_isspace(" ".ord, Encoding::UTF_8).should == true
end
it "returns zero for non space characters" do
@s.rb_enc_isspace("-".ord, Encoding::US_ASCII).should == false
@s.rb_enc_isspace("A".ord, Encoding::US_ASCII).should == false
@s.rb_enc_isspace("3".ord, Encoding::US_ASCII).should == false
@s.rb_enc_isspace("-".ord, Encoding::UTF_8).should == false
@s.rb_enc_isspace("A".ord, Encoding::UTF_8).should == false
@s.rb_enc_isspace("3".ord, Encoding::UTF_8).should == false
end
end
describe "rb_enc_from_index" do
it "returns an Encoding" do
@s.rb_enc_from_index(0).should be_an_instance_of(String)
end
end
describe "rb_enc_mbc_to_codepoint" do
it "returns the correct codepoint for the given character and size" do
@s.rb_enc_mbc_to_codepoint("é", 2).should == 0x00E9
@s.rb_enc_mbc_to_codepoint("éa", 2).should == 0x00E9
@s.rb_enc_mbc_to_codepoint("éa", 1).should == 0xC3
@s.rb_enc_mbc_to_codepoint("éa", 3).should == 0x00E9
end
end
describe "rb_usascii_encoding" do
it "returns the encoding for Encoding::US_ASCII" do
@s.rb_usascii_encoding.should == "US-ASCII"

View file

@ -162,6 +162,14 @@ static VALUE array_spec_rb_ary_shift(VALUE self, VALUE array) {
return rb_ary_shift(array);
}
static VALUE array_spec_rb_ary_sort(VALUE self, VALUE array) {
return rb_ary_sort(array);
}
static VALUE array_spec_rb_ary_sort_bang(VALUE self, VALUE array) {
return rb_ary_sort_bang(array);
}
static VALUE array_spec_rb_ary_store(VALUE self, VALUE array, VALUE offset, VALUE value) {
rb_ary_store(array, FIX2INT(offset), value);
@ -272,6 +280,8 @@ void Init_array_spec(void) {
rb_define_method(cls, "rb_ary_reverse", array_spec_rb_ary_reverse, 1);
rb_define_method(cls, "rb_ary_rotate", array_spec_rb_ary_rotate, 2);
rb_define_method(cls, "rb_ary_shift", array_spec_rb_ary_shift, 1);
rb_define_method(cls, "rb_ary_sort", array_spec_rb_ary_sort, 1);
rb_define_method(cls, "rb_ary_sort_bang", array_spec_rb_ary_sort_bang, 1);
rb_define_method(cls, "rb_ary_store", array_spec_rb_ary_store, 3);
rb_define_method(cls, "rb_ary_concat", array_spec_rb_ary_concat, 2);
rb_define_method(cls, "rb_ary_plus", array_spec_rb_ary_plus, 2);

View file

@ -106,10 +106,27 @@ static VALUE encoding_spec_rb_enc_find_index(VALUE self, VALUE name) {
return INT2NUM(rb_enc_find_index(RSTRING_PTR(name)));
}
static VALUE encoding_spec_rb_enc_isalnum(VALUE self, VALUE chr, VALUE encoding) {
rb_encoding *e = rb_to_encoding(encoding);
return rb_enc_isalnum(FIX2INT(chr), e) ? Qtrue : Qfalse;
}
static VALUE encoding_spec_rb_enc_isspace(VALUE self, VALUE chr, VALUE encoding) {
rb_encoding *e = rb_to_encoding(encoding);
return rb_enc_isspace(FIX2INT(chr), e) ? Qtrue : Qfalse;
}
static VALUE encoding_spec_rb_enc_from_index(VALUE self, VALUE index) {
return rb_str_new2(rb_enc_from_index(NUM2INT(index))->name);
}
static VALUE encoding_spec_rb_enc_mbc_to_codepoint(VALUE self, VALUE str, VALUE offset) {
int o = FIX2INT(offset);
char *p = RSTRING_PTR(str);
char *e = p + o;
return INT2FIX(rb_enc_mbc_to_codepoint(p, e, rb_enc_get(str)));
}
static VALUE encoding_spec_rb_enc_from_encoding(VALUE self, VALUE name) {
return rb_enc_from_encoding(rb_enc_find(RSTRING_PTR(name)));
}
@ -284,7 +301,10 @@ void Init_encoding_spec(void) {
rb_define_method(cls, "rb_enc_copy", encoding_spec_rb_enc_copy, 2);
rb_define_method(cls, "rb_enc_find", encoding_spec_rb_enc_find, 1);
rb_define_method(cls, "rb_enc_find_index", encoding_spec_rb_enc_find_index, 1);
rb_define_method(cls, "rb_enc_isalnum", encoding_spec_rb_enc_isalnum, 2);
rb_define_method(cls, "rb_enc_isspace", encoding_spec_rb_enc_isspace, 2);
rb_define_method(cls, "rb_enc_from_index", encoding_spec_rb_enc_from_index, 1);
rb_define_method(cls, "rb_enc_mbc_to_codepoint", encoding_spec_rb_enc_mbc_to_codepoint, 2);
rb_define_method(cls, "rb_enc_from_encoding", encoding_spec_rb_enc_from_encoding, 1);
rb_define_method(cls, "rb_enc_get", encoding_spec_rb_enc_get, 1);
rb_define_method(cls, "rb_enc_precise_mbclen", encoding_spec_rb_enc_precise_mbclen, 2);

View file

@ -105,6 +105,12 @@ VALUE hash_spec_rb_hash_new(VALUE self) {
return rb_hash_new();
}
VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */
VALUE hash_spec_rb_ident_hash_new(VALUE self) {
return rb_ident_hash_new();
}
VALUE hash_spec_rb_hash_size(VALUE self, VALUE hash) {
return rb_hash_size(hash);
}
@ -143,6 +149,7 @@ void Init_hash_spec(void) {
rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3);
rb_define_method(cls, "rb_hash_lookup2_default_undef", hash_spec_rb_hash_lookup2_default_undef, 2);
rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0);
rb_define_method(cls, "rb_ident_hash_new", hash_spec_rb_ident_hash_new, 0);
rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1);
rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2);
rb_define_method(cls, "compute_a_hash_code", hash_spec_compute_a_hash_code, 1);

View file

@ -13,6 +13,12 @@ static VALUE integer_spec_rb_integer_pack(VALUE self, VALUE value,
return INT2FIX(result);
}
VALUE rb_int_positive_pow(long x, unsigned long y); /* internal.h, used in ripper */
static VALUE integer_spec_rb_int_positive_pow(VALUE self, VALUE a, VALUE b){
return rb_int_positive_pow(FIX2INT(a), FIX2INT(b));
}
void Init_integer_spec(void) {
VALUE cls = rb_define_class("CApiIntegerSpecs", rb_cObject);
rb_define_const(cls, "MSWORD", INT2NUM(INTEGER_PACK_MSWORD_FIRST));
@ -27,6 +33,7 @@ void Init_integer_spec(void) {
rb_define_const(cls, "NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE));
rb_define_method(cls, "rb_integer_pack", integer_spec_rb_integer_pack, 6);
rb_define_method(cls, "rb_int_positive_pow", integer_spec_rb_int_positive_pow, 2);
}
#ifdef __cplusplus

View file

@ -9,8 +9,10 @@
extern "C" {
#endif
VALUE regexp_spec_re(VALUE self) {
return rb_reg_new("a", 1, 0);
VALUE regexp_spec_re(VALUE self, VALUE str, VALUE options) {
char *cstr = StringValueCStr(str);
int opts = FIX2INT(options);
return rb_reg_new(cstr, strlen(cstr), opts);
}
VALUE regexp_spec_reg_1st_match(VALUE self, VALUE md) {
@ -40,7 +42,7 @@ VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) {
void Init_regexp_spec(void) {
VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject);
rb_define_method(cls, "match", regexp_spec_match, 2);
rb_define_method(cls, "a_re", regexp_spec_re, 0);
rb_define_method(cls, "a_re", regexp_spec_re, 2);
rb_define_method(cls, "a_re_1st_match", regexp_spec_reg_1st_match, 1);
rb_define_method(cls, "rb_reg_match", regexp_spec_reg_match, 2);
rb_define_method(cls, "rb_backref_get", regexp_spec_backref_get, 0);

View file

@ -91,6 +91,12 @@ VALUE string_spec_rb_str_buf_cat(VALUE self, VALUE str) {
return str;
}
VALUE string_spec_rb_enc_str_buf_cat(VALUE self, VALUE str, VALUE other, VALUE encoding) {
char *cstr = StringValueCStr(other);
rb_encoding* enc = rb_to_encoding(encoding);
return rb_enc_str_buf_cat(str, cstr, strlen(cstr), enc);
}
VALUE string_spec_rb_str_cat(VALUE self, VALUE str) {
return rb_str_cat(str, "?", 1);
}
@ -432,6 +438,14 @@ static VALUE string_spec_rb_usascii_str_new(VALUE self, VALUE str, VALUE len) {
return rb_usascii_str_new(RSTRING_PTR(str), NUM2INT(len));
}
static VALUE string_spec_rb_usascii_str_new_lit(VALUE self) {
return rb_usascii_str_new_lit("nokogiri");
}
static VALUE string_spec_rb_usascii_str_new_lit_non_ascii(VALUE self) {
return rb_usascii_str_new_lit("r\u00E9sum\u00E9");
}
static VALUE string_spec_rb_usascii_str_new_cstr(VALUE self, VALUE str) {
return rb_usascii_str_new_cstr(RSTRING_PTR(str));
}
@ -475,6 +489,7 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_str_tmp_new", string_spec_rb_str_tmp_new, 1);
rb_define_method(cls, "rb_str_tmp_new_klass", string_spec_rb_str_tmp_new_klass, 1);
rb_define_method(cls, "rb_str_buf_cat", string_spec_rb_str_buf_cat, 1);
rb_define_method(cls, "rb_enc_str_buf_cat", string_spec_rb_enc_str_buf_cat, 3);
rb_define_method(cls, "rb_str_cat", string_spec_rb_str_cat, 1);
rb_define_method(cls, "rb_str_cat2", string_spec_rb_str_cat2, 1);
rb_define_method(cls, "rb_str_cat_cstr", string_spec_rb_str_cat_cstr, 2);
@ -539,6 +554,8 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4);
rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2);
rb_define_method(cls, "rb_usascii_str_new", string_spec_rb_usascii_str_new, 2);
rb_define_method(cls, "rb_usascii_str_new_lit", string_spec_rb_usascii_str_new_lit, 0);
rb_define_method(cls, "rb_usascii_str_new_lit_non_ascii", string_spec_rb_usascii_str_new_lit_non_ascii, 0);
rb_define_method(cls, "rb_usascii_str_new_cstr", string_spec_rb_usascii_str_new_cstr, 1);
rb_define_method(cls, "rb_String", string_spec_rb_String, 1);
rb_define_method(cls, "rb_string_value_cstr", string_spec_rb_string_value_cstr, 1);

View file

@ -50,6 +50,14 @@ describe "C-API Hash function" do
end
end
describe "rb_ident_hash_new" do
it "returns a new compare by identity hash" do
result = @s.rb_ident_hash_new
result.should == {}
result.compare_by_identity?.should == true
end
end
describe "rb_hash_dup" do
it "returns a copy of the hash" do
hsh = {}

View file

@ -272,4 +272,19 @@ describe "CApiIntegerSpecs" do
end
end
end
describe "rb_int_positive_pow" do
it "raises an integer to given power" do
@s.rb_int_positive_pow(2, 3).should == 8
end
it "raises a negative integer to given power" do
@s.rb_int_positive_pow(-2, 3).should == -8
@s.rb_int_positive_pow(-2, 4).should == 16
end
it "overflows for large inputs" do
@s.rb_int_positive_pow(8, 23).should == 590295810358705651712
end
end
end

View file

@ -9,12 +9,20 @@ describe "C-API Regexp function" do
describe "rb_reg_new" do
it "returns a new valid Regexp" do
my_re = @p.a_re
my_re = @p.a_re("a", 0)
my_re.kind_of?(Regexp).should == true
('1a' =~ my_re).should == 1
('1b' =~ my_re).should == nil
my_re.source.should == 'a'
end
it "returns a Regexp with the given options" do
@p.a_re("a", 0).options == 0
@p.a_re("a", Regexp::IGNORECASE).options.should == Regexp::IGNORECASE
@p.a_re("a", Regexp::EXTENDED).options.should == Regexp::EXTENDED
@p.a_re("a", Regexp::EXTENDED | Regexp::IGNORECASE).options.should == Regexp::EXTENDED | Regexp::IGNORECASE
@p.a_re("a", Regexp::MULTILINE).options.should == Regexp::MULTILINE
end
end
describe "rb_reg_nth_match" do

View file

@ -218,6 +218,20 @@ describe "C-API String function" do
end
end
describe "rb_usascii_str_new_lit" do
it "returns a US-ASCII string of the correct characters" do
str = @s.rb_usascii_str_new_lit
str.should == "nokogiri"
str.encoding.should == Encoding::US_ASCII
end
it "returns US-ASCII string for non-US-ASCII string literal" do
str = @s.rb_usascii_str_new_lit_non_ascii
str.should == "r\xC3\xA9sum\xC3\xA9".force_encoding(Encoding::US_ASCII)
str.encoding.should == Encoding::US_ASCII
end
end
describe "rb_usascii_str_new_cstr" do
it "creates a new String with US-ASCII Encoding" do
str = "abc".force_encoding("us-ascii")
@ -392,6 +406,16 @@ describe "C-API String function" do
end
end
describe "rb_enc_str_buf_cat" do
it "concatenates a C string literal to a ruby string with the given encoding" do
input = "hello ".force_encoding(Encoding::US_ASCII)
result = @s.rb_enc_str_buf_cat(input, "résumé", Encoding::UTF_8)
result.should == "hello résumé"
result.encoding.should == Encoding::UTF_8
result.object_id.should == input.object_id
end
end
describe "rb_str_cmp" do
it "returns 0 if two strings are identical" do
@s.rb_str_cmp("ppp", "ppp").should == 0