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: Exclude:
- library/coverage/fixtures/some_class.rb - library/coverage/fixtures/some_class.rb
Layout/SpaceInLambdaLiteral:
Enabled: true
EnforcedStyle: require_space
Lint: Lint:
Enabled: true Enabled: true

View file

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

View file

@ -323,6 +323,10 @@ describe "Array#[]= with [index, count]" do
b = [1, 2, 3, 4, 5] b = [1, 2, 3, 4, 5]
b[10, 0] = [1] b[10, 0] = [1]
a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 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 end
it "inserts other section in place defined by idx" do 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 it "raises a ZeroDivisionError when the given argument is 0" do
-> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError) -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError)
end 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
end end

View file

@ -66,6 +66,10 @@ describe "IO#ungetbyte" do
end end
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 it "raises an IOError if the IO is closed" do
@io.close @io.close
-> { @io.ungetbyte(42) }.should raise_error(IOError) -> { @io.ungetbyte(42) }.should raise_error(IOError)

View file

@ -136,6 +136,10 @@ describe "IO#ungetc" do
@io.ungetc(100).should be_nil @io.ungetc(100).should be_nil
end 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 it "raises IOError on closed stream" do
@io.getc @io.getc
@io.close @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 end
describe "Kernel#proc" do describe "Kernel#proc" do
def some_method
proc
end
ruby_version_is ""..."2.7" do ruby_version_is ""..."2.7" do
it "uses the implicit block from an enclosing method" do it "uses the implicit block from an enclosing method" do
def some_method
proc
end
prc = some_method { "hello" } prc = some_method { "hello" }
prc.call.should == "hello" prc.call.should == "hello"
end end
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 it "can be created when called with no block" do
def some_method
proc
end
-> { -> {
some_method { "hello" } some_method { "hello" }
}.should complain(/Capturing the given block using Kernel#proc is deprecated/) }.should complain(/Capturing the given block using Kernel#proc is deprecated/)
end end
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 end

View file

@ -11,6 +11,10 @@ describe "Kernel.srand" do
srand(20).should == 10 srand(20).should == 10
end 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 it "seeds the RNG correctly and repeatably" do
srand(10) srand(10)
x = rand x = rand

View file

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

View file

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

View file

@ -203,7 +203,7 @@ describe "Proc.new without a block" do
end end
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 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/) -> { ProcSpecs.new_proc_in_method { "hello" } }.should complain(/Capturing the given block using Proc.new is deprecated/)
end end
@ -223,4 +223,16 @@ describe "Proc.new without a block" do
}.should complain(/Capturing the given block using Proc.new is deprecated/) }.should complain(/Capturing the given block using Proc.new is deprecated/)
end end
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 end

View file

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

View file

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

View file

@ -1,14 +1,19 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
describe "Symbol.all_symbols" do 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 = Symbol.all_symbols
all_symbols.should be_an_instance_of(Array) 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 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 = "symbol_specs_#{rand(5_000_000)}".to_sym
Symbol.all_symbols.should include(symbol) Symbol.all_symbols.should include(symbol)
end 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 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) -> { m(1, 2, *x) }.should raise_error(TypeError)
end end
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 end
describe "An element assignment method send" do describe "An element assignment method send" do

View file

@ -23,11 +23,41 @@ describe "The rescue keyword" do
end.should == :caught end.should == :caught
end end
it "can capture the raised exception in a local variable" do describe 'can capture the raised exception' do
begin before :all do
raise SpecificExampleException, "some text" require_relative 'fixtures/rescue_captures'
rescue SpecificExampleException => e end
e.message.should == "some text"
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
end end

View file

@ -102,6 +102,37 @@ describe "The super keyword" do
c2.new.m(:dump) { :value }.should == :value c2.new.m(:dump) { :value }.should == :value
end 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 it "uses block argument given to method when used in a block" do
c1 = Class.new do c1 = Class.new do
def m def m

View file

@ -28,8 +28,7 @@ describe 'RbConfig::CONFIG' do
ruby_exe(<<-RUBY, options: '--enable-frozen-string-literal').should == "Done\n" ruby_exe(<<-RUBY, options: '--enable-frozen-string-literal').should == "Done\n"
require 'rbconfig' require 'rbconfig'
RbConfig::CONFIG.each do |k, v| RbConfig::CONFIG.each do |k, v|
# SDKROOT excluded here to workaround the issue: https://bugs.ruby-lang.org/issues/16738 if v.frozen?
if v.frozen? && k != 'SDKROOT'
puts "\#{k} Failure" puts "\#{k} Failure"
end end
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.should raise_error(StandardError)
end 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 it "returns back the last value in the block" do
Timeout.timeout(1) do Timeout.timeout(1) do
42 42

View file

@ -190,6 +190,22 @@ describe "C-API Array function" do
end end
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 describe "rb_ary_store" do
it "overwrites the element at the given position" do it "overwrites the element at the given position" do
a = [1, 2, 3] a = [1, 2, 3]

View file

@ -82,12 +82,54 @@ describe "C-API Encoding function" do
end end
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 describe "rb_enc_from_index" do
it "returns an Encoding" do it "returns an Encoding" do
@s.rb_enc_from_index(0).should be_an_instance_of(String) @s.rb_enc_from_index(0).should be_an_instance_of(String)
end end
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 describe "rb_usascii_encoding" do
it "returns the encoding for Encoding::US_ASCII" do it "returns the encoding for Encoding::US_ASCII" do
@s.rb_usascii_encoding.should == "US-ASCII" @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); 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) { static VALUE array_spec_rb_ary_store(VALUE self, VALUE array, VALUE offset, VALUE value) {
rb_ary_store(array, FIX2INT(offset), 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_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_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_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_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_concat", array_spec_rb_ary_concat, 2);
rb_define_method(cls, "rb_ary_plus", array_spec_rb_ary_plus, 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))); 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) { static VALUE encoding_spec_rb_enc_from_index(VALUE self, VALUE index) {
return rb_str_new2(rb_enc_from_index(NUM2INT(index))->name); 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) { static VALUE encoding_spec_rb_enc_from_encoding(VALUE self, VALUE name) {
return rb_enc_from_encoding(rb_enc_find(RSTRING_PTR(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_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", 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_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_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_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_get", encoding_spec_rb_enc_get, 1);
rb_define_method(cls, "rb_enc_precise_mbclen", encoding_spec_rb_enc_precise_mbclen, 2); 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(); 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) { VALUE hash_spec_rb_hash_size(VALUE self, VALUE hash) {
return rb_hash_size(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", 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_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_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_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, "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); 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); 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) { void Init_integer_spec(void) {
VALUE cls = rb_define_class("CApiIntegerSpecs", rb_cObject); VALUE cls = rb_define_class("CApiIntegerSpecs", rb_cObject);
rb_define_const(cls, "MSWORD", INT2NUM(INTEGER_PACK_MSWORD_FIRST)); 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_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_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 #ifdef __cplusplus

View file

@ -9,8 +9,10 @@
extern "C" { extern "C" {
#endif #endif
VALUE regexp_spec_re(VALUE self) { VALUE regexp_spec_re(VALUE self, VALUE str, VALUE options) {
return rb_reg_new("a", 1, 0); 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) { 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) { void Init_regexp_spec(void) {
VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject); VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject);
rb_define_method(cls, "match", regexp_spec_match, 2); 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, "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_reg_match", regexp_spec_reg_match, 2);
rb_define_method(cls, "rb_backref_get", regexp_spec_backref_get, 0); 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; 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) { VALUE string_spec_rb_str_cat(VALUE self, VALUE str) {
return rb_str_cat(str, "?", 1); 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)); 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) { static VALUE string_spec_rb_usascii_str_new_cstr(VALUE self, VALUE str) {
return rb_usascii_str_new_cstr(RSTRING_PTR(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", 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_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_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_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_cat2", string_spec_rb_str_cat2, 1);
rb_define_method(cls, "rb_str_cat_cstr", string_spec_rb_str_cat_cstr, 2); 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_vsprintf", string_spec_rb_vsprintf, 4);
rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2); 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", 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_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", string_spec_rb_String, 1);
rb_define_method(cls, "rb_string_value_cstr", string_spec_rb_string_value_cstr, 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
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 describe "rb_hash_dup" do
it "returns a copy of the hash" do it "returns a copy of the hash" do
hsh = {} hsh = {}

View file

@ -272,4 +272,19 @@ describe "CApiIntegerSpecs" do
end end
end 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 end

View file

@ -9,12 +9,20 @@ describe "C-API Regexp function" do
describe "rb_reg_new" do describe "rb_reg_new" do
it "returns a new valid Regexp" 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 my_re.kind_of?(Regexp).should == true
('1a' =~ my_re).should == 1 ('1a' =~ my_re).should == 1
('1b' =~ my_re).should == nil ('1b' =~ my_re).should == nil
my_re.source.should == 'a' my_re.source.should == 'a'
end 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 end
describe "rb_reg_nth_match" do describe "rb_reg_nth_match" do

View file

@ -218,6 +218,20 @@ describe "C-API String function" do
end end
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 describe "rb_usascii_str_new_cstr" do
it "creates a new String with US-ASCII Encoding" do it "creates a new String with US-ASCII Encoding" do
str = "abc".force_encoding("us-ascii") str = "abc".force_encoding("us-ascii")
@ -392,6 +406,16 @@ describe "C-API String function" do
end end
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 describe "rb_str_cmp" do
it "returns 0 if two strings are identical" do it "returns 0 if two strings are identical" do
@s.rb_str_cmp("ppp", "ppp").should == 0 @s.rb_str_cmp("ppp", "ppp").should == 0