1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
* Specs added by TruffleRuby.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2018-06-13 21:58:54 +00:00
parent 5b55eaa00d
commit b46da8d84e
24 changed files with 812 additions and 57 deletions

View file

@ -11,6 +11,11 @@ describe 'The -C command line option' do
output.should == @tempdir output.should == @tempdir
end end
it 'does not need a space after -C for the argument' do
output = ruby_exe(@script, options: "-C#{@tempdir}")
output.should == @tempdir
end
it 'changes the PWD when using -e' do it 'changes the PWD when using -e' do
output = ruby_exe(nil, options: "-C #{@tempdir} -e 'print Dir.pwd'") output = ruby_exe(nil, options: "-C #{@tempdir} -e 'print Dir.pwd'")
output.should == @tempdir output.should == @tempdir

View file

@ -3,7 +3,7 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is '2.4' do ruby_version_is '2.4' do
describe "Aray#pack with `buffer` option" do describe "Array#pack with :buffer option" do
it "returns specified buffer" do it "returns specified buffer" do
n = [ 65, 66, 67 ] n = [ 65, 66, 67 ]
buffer = " "*3 buffer = " "*3
@ -36,7 +36,7 @@ ruby_version_is '2.4' do
n.pack("@3ccc", buffer: buffer).should == "123ABC" n.pack("@3ccc", buffer: buffer).should == "123ABC"
end end
it "fills the gap with \0 if buffer content is shorter than offset" do it "fills the gap with \\0 if buffer content is shorter than offset" do
n = [ 65, 66, 67 ] n = [ 65, 66, 67 ]
buffer = "123" buffer = "123"
n.pack("@6ccc", buffer: buffer).should == "123\0\0\0ABC" n.pack("@6ccc", buffer: buffer).should == "123\0\0\0ABC"

View file

@ -177,4 +177,12 @@ end
end end
err.backtrace.first.split(":")[0..1].should == ["b_file", "-98"] err.backtrace.first.split(":")[0..1].should == ["b_file", "-98"]
end end
it "has access to the caller's local variables" do
x = nil
instance_eval "x = :value"
x.should == :value
end
end end

View file

@ -0,0 +1,61 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
describe "Exception#dup" do
before :each do
@obj = ExceptionSpecs::InitializeException.new("my exception")
end
it "calls #initialize_copy on the new instance" do
dup = @obj.dup
ScratchPad.recorded.should_not == @obj.object_id
ScratchPad.recorded.should == dup.object_id
end
it "copies instance variables" do
dup = @obj.dup
dup.ivar.should == 1
end
it "does not copy singleton methods" do
def @obj.special() :the_one end
dup = @obj.dup
lambda { dup.special }.should raise_error(NameError)
end
it "does not copy modules included in the singleton class" do
class << @obj
include ExceptionSpecs::ExceptionModule
end
dup = @obj.dup
lambda { dup.repr }.should raise_error(NameError)
end
it "does not copy constants defined in the singleton class" do
class << @obj
CLONE = :clone
end
dup = @obj.dup
lambda { class << dup; CLONE; end }.should raise_error(NameError)
end
it "does copy the message" do
@obj.dup.message.should == @obj.message
end
it "does copy the backtrace" do
begin
# Explicitly raise so a backtrace is associated with the exception.
# It's tempting to call `set_backtrace` instead, but that complicates
# the test because it might affect other state (e.g., instance variables)
# on some implementations.
raise ExceptionSpecs::InitializeException.new("my exception")
rescue => e
@obj = e
end
@obj.dup.backtrace.should == @obj.backtrace
end
end

View file

@ -46,6 +46,26 @@ module ExceptionSpecs
"" ""
end end
end end
class InitializeException < StandardError
attr_reader :ivar
def initialize(message = nil)
super
@ivar = 1
end
def initialize_copy(other)
super
ScratchPad.record object_id
end
end
module ExceptionModule
def repr
1
end
end
end end
module NoMethodErrorSpecs module NoMethodErrorSpecs

View file

@ -109,8 +109,8 @@ describe "File.expand_path" do
File.expand_path(Dir.pwd).should == Dir.pwd File.expand_path(Dir.pwd).should == Dir.pwd
File.expand_path('~/').should == @home File.expand_path('~/').should == @home
File.expand_path('~/..badfilename').should == "#{@home}/..badfilename" File.expand_path('~/..badfilename').should == "#{@home}/..badfilename"
File.expand_path('..').should == Dir.pwd.split('/')[0...-1].join("/")
File.expand_path('~/a','~/b').should == "#{@home}/a" File.expand_path('~/a','~/b').should == "#{@home}/a"
File.expand_path('..').should == File.dirname(Dir.pwd)
end end
it "does not replace multiple '/' at the beginning of the path" do it "does not replace multiple '/' at the beginning of the path" do

View file

@ -5,17 +5,11 @@ module FileSpecs
@file = tmp("test.txt") @file = tmp("test.txt")
@dir = Dir.pwd @dir = Dir.pwd
@fifo = tmp("test_fifo") @fifo = tmp("test_fifo")
@link = tmp("test_link")
platform_is_not :windows do platform_is_not :windows do
@block = `find /dev /devices -type b 2> /dev/null`.split("\n").first @block = `find /dev /devices -type b 2>/dev/null`.split("\n").first
@char = `{ tty || find /dev /devices -type c; } 2> /dev/null`.split("\n").last @char = `{ tty || find /dev /devices -type c; } 2>/dev/null`.split("\n").last
%w[/dev /usr/bin /usr/local/bin].each do |dir|
links = `find #{dir} -type l 2> /dev/null`.split("\n")
next if links.empty?
@link = links.first
break
end
end end
@configured = true @configured = true
@ -32,24 +26,29 @@ module FileSpecs
yield @dir yield @dir
end end
# TODO: need a platform-independent helper here
def self.fifo def self.fifo
system "mkfifo #{@fifo} 2> /dev/null" File.mkfifo(@fifo)
yield @fifo yield @fifo
ensure ensure
rm_r @fifo rm_r @fifo
end end
def self.block_device def self.block_device
raise "Could not find a block device" unless @block
yield @block yield @block
end end
def self.character_device def self.character_device
raise "Could not find a character device" unless @char
yield @char yield @char
end end
def self.symlink def self.symlink
touch(@file)
File.symlink(@file, @link)
yield @link yield @link
ensure
rm_r @file, @link
end end
def self.socket def self.socket
@ -57,8 +56,11 @@ module FileSpecs
name = tmp("ftype_socket.socket") name = tmp("ftype_socket.socket")
rm_r name rm_r name
socket = UNIXServer.new name socket = UNIXServer.new name
begin
yield name yield name
ensure
socket.close socket.close
rm_r name rm_r name
end end
end
end end

View file

@ -604,7 +604,7 @@ describe "File.open" do
describe "on a FIFO" do describe "on a FIFO" do
before :each do before :each do
@fifo = tmp("File_open_fifo") @fifo = tmp("File_open_fifo")
system "mkfifo #{@fifo}" File.mkfifo(@fifo)
end end
after :each do after :each do

View file

@ -22,7 +22,7 @@ describe "File.pipe?" do
platform_is_not :windows do platform_is_not :windows do
it "returns true if the file is a pipe" do it "returns true if the file is a pipe" do
filename = tmp("i_am_a_pipe") filename = tmp("i_am_a_pipe")
system "mkfifo #{filename}" File.mkfifo(filename)
File.pipe?(filename).should == true File.pipe?(filename).should == true

View file

@ -20,7 +20,7 @@ describe "File::Stat#pipe?" do
platform_is_not :windows do platform_is_not :windows do
it "returns true if the file is a pipe" do it "returns true if the file is a pipe" do
filename = tmp("i_am_a_pipe") filename = tmp("i_am_a_pipe")
system "mkfifo #{filename}" File.mkfifo(filename)
st = File.stat(filename) st = File.stat(filename)
st.pipe?.should == true st.pipe?.should == true

View file

@ -0,0 +1,15 @@
require_relative '../../spec_helper'
ruby_version_is '2.4' do
describe "Integer#dup" do
it "returns self for small integers" do
integer = 1_000
integer.dup.should equal(integer)
end
it "returns self for large integers" do
integer = 4_611_686_018_427_387_905
integer.dup.should equal(integer)
end
end
end

View file

@ -103,7 +103,7 @@ describe "IO.write" do
describe "on a FIFO" do describe "on a FIFO" do
before :each do before :each do
@fifo = tmp("File_open_fifo") @fifo = tmp("File_open_fifo")
system "mkfifo #{@fifo}" File.mkfifo(@fifo)
end end
after :each do after :each do

View file

@ -539,6 +539,16 @@ describe "Marshal.dump" do
end end
describe "when passed a StringIO" do
it "should raise an error" do
require "stringio"
lambda { Marshal.dump(StringIO.new) }.should raise_error(TypeError)
end
end
it "raises a TypeError if marshalling a Method instance" do it "raises a TypeError if marshalling a Method instance" do
lambda { Marshal.dump(Marshal.method(:dump)) }.should raise_error(TypeError) lambda { Marshal.dump(Marshal.method(:dump)) }.should raise_error(TypeError)
end end

View file

@ -26,8 +26,65 @@ describe "String#capitalize" do
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "works for all of Unicode" do describe "full Unicode case mapping" do
"äöü".capitalize.should == "Äöü" it "works for all of Unicode with no option" do
"äöÜ".capitalize.should == "Äöü"
end
it "only capitalizes the first resulting character when upcasing a character produces a multi-character sequence" do
"ß".capitalize.should == "Ss"
end
it "updates string metadata" do
capitalized = "ßeT".capitalize
capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
capitalized.ascii_only?.should be_true
end
end
describe "ASCII-only case mapping" do
it "does not capitalize non-ASCII characters" do
"ßet".capitalize(:ascii).should == "ßet"
end
end
describe "full Unicode case mapping adapted for Turkic languages" do
it "capitalizes ASCII characters according to Turkic semantics" do
"iSa".capitalize(:turkic).should == "İsa"
end
it "allows Lithuanian as an extra option" do
"iSa".capitalize(:turkic, :lithuanian).should == "İsa"
end
it "does not allow any other additional option" do
lambda { "iSa".capitalize(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
"".capitalize(:lithuanian).should == ""
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
"".capitalize(:lithuanian, :turkic).should == "İß"
end
it "does not allow any other additional option" do
lambda { "".capitalize(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
lambda { "abc".capitalize(:fold) }.should raise_error(ArgumentError)
end
it "does not allow invalid options" do
lambda { "abc".capitalize(:invalid_option) }.should raise_error(ArgumentError)
end end
end end
@ -45,11 +102,81 @@ describe "String#capitalize!" do
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "capitalizes self in place for all of Unicode" do describe "full Unicode case mapping" do
a = "äöü" it "modifies self in place for all of Unicode with no option" do
a.capitalize!.should equal(a) a = "äöÜ"
a.capitalize!
a.should == "Äöü" a.should == "Äöü"
end end
it "only capitalizes the first resulting character when upcasing a character produces a multi-character sequence" do
a = "ß"
a.capitalize!
a.should == "Ss"
end
it "updates string metadata" do
capitalized = "ßeT"
capitalized.capitalize!
capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
capitalized.ascii_only?.should be_true
end
end
describe "modifies self in place for ASCII-only case mapping" do
it "does not capitalize non-ASCII characters" do
a = "ßet"
a.capitalize!(:ascii)
a.should == "ßet"
end
end
describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do
it "capitalizes ASCII characters according to Turkic semantics" do
a = "iSa"
a.capitalize!(:turkic)
a.should == "İsa"
end
it "allows Lithuanian as an extra option" do
a = "iSa"
a.capitalize!(:turkic, :lithuanian)
a.should == "İsa"
end
it "does not allow any other additional option" do
lambda { a = "iSa"; a.capitalize!(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "modifies self in place for full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
a = ""
a.capitalize!(:lithuanian)
a.should == ""
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
a = ""
a.capitalize!(:lithuanian, :turkic)
a.should == "İß"
end
it "does not allow any other additional option" do
lambda { a = ""; a.capitalize!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
lambda { a = "abc"; a.capitalize!(:fold) }.should raise_error(ArgumentError)
end
it "does not allow invalid options" do
lambda { a = "abc"; a.capitalize!(:invalid_option) }.should raise_error(ArgumentError)
end
end end
it "returns nil when no changes are made" do it "returns nil when no changes are made" do

View file

@ -37,6 +37,10 @@ describe "String#casecmp independent of case" do
end end
end end
it "returns nil if incompatible encodings" do
"あれ".casecmp("".encode(Encoding::EUC_JP)).should be_nil
end
describe "in UTF-8 mode" do describe "in UTF-8 mode" do
describe "for non-ASCII characters" do describe "for non-ASCII characters" do
before :each do before :each do
@ -96,6 +100,12 @@ describe "String#casecmp independent of case" do
it "returns 1 when numerically greater than other" do it "returns 1 when numerically greater than other" do
@lower_a_tilde.casecmp(@upper_a_tilde).should == 1 @lower_a_tilde.casecmp(@upper_a_tilde).should == 1
end end
ruby_version_is "2.4" do
it "does not case fold" do
"ß".casecmp("ss").should == 1
end
end
end end
describe "when comparing a subclass instance" do describe "when comparing a subclass instance" do
@ -138,6 +148,10 @@ ruby_version_is "2.4" do
"abc".casecmp?(other).should == true "abc".casecmp?(other).should == true
end end
it "returns nil if incompatible encodings" do
"あれ".casecmp?("".encode(Encoding::EUC_JP)).should be_nil
end
describe 'for UNICODE characters' do describe 'for UNICODE characters' do
it 'returns true when downcase(:fold) on unicode' do it 'returns true when downcase(:fold) on unicode' do
'äöü'.casecmp?('ÄÖÜ').should == true 'äöü'.casecmp?('ÄÖÜ').should == true
@ -181,6 +195,12 @@ ruby_version_is "2.4" do
end end
end end
ruby_version_is "2.4" do
it "case folds" do
"ß".casecmp?("ss").should be_true
end
end
ruby_version_is "2.4" ... "2.5" do ruby_version_is "2.4" ... "2.5" do
it "raises a TypeError if other can't be converted to a string" do it "raises a TypeError if other can't be converted to a string" do
lambda { "abc".casecmp?(mock('abc')) }.should raise_error(TypeError) lambda { "abc".casecmp?(mock('abc')) }.should raise_error(TypeError)

View file

@ -23,9 +23,65 @@ describe "String#downcase" do
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "works for all of Unicode" do describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do
"ÄÖÜ".downcase.should == "äöü" "ÄÖÜ".downcase.should == "äöü"
end end
it "updates string metadata" do
downcased = "\u{212A}ING".downcase
downcased.should == "king"
downcased.size.should == 4
downcased.bytesize.should == 4
downcased.ascii_only?.should be_true
end
end
describe "ASCII-only case mapping" do
it "does not downcase non-ASCII characters" do
"CÅR".downcase(:ascii).should == "cÅr"
end
end
describe "full Unicode case mapping adapted for Turkic languages" do
it "downcases characters according to Turkic semantics" do
"İ".downcase(:turkic).should == "i"
end
it "allows Lithuanian as an extra option" do
"İ".downcase(:turkic, :lithuanian).should == "i"
end
it "does not allow any other additional option" do
lambda { "İ".downcase(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
"İS".downcase(:lithuanian).should == "i\u{307}s"
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
"İS".downcase(:lithuanian, :turkic).should == "is"
end
it "does not allow any other additional option" do
lambda { "İS".downcase(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
describe "case folding" do
it "case folds special characters" do
"ß".downcase.should == "ß"
"ß".downcase(:fold).should == "ss"
end
end
it "does not allow invalid options" do
lambda { "ABC".downcase(:invalid_option) }.should raise_error(ArgumentError)
end
end end
it "taints result when self is tainted" do it "taints result when self is tainted" do
@ -47,11 +103,82 @@ describe "String#downcase!" do
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "modifies self in place for all of Unicode" do describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
a = "ÄÖÜ" a = "ÄÖÜ"
a.downcase!.should equal(a) a.downcase!
a.should == "äöü" a.should == "äöü"
end end
it "updates string metadata" do
downcased = "\u{212A}ING"
downcased.downcase!
downcased.should == "king"
downcased.size.should == 4
downcased.bytesize.should == 4
downcased.ascii_only?.should be_true
end
end
describe "ASCII-only case mapping" do
it "does not downcase non-ASCII characters" do
a = "CÅR"
a.downcase!(:ascii)
a.should == "cÅr"
end
end
describe "full Unicode case mapping adapted for Turkic languages" do
it "downcases characters according to Turkic semantics" do
a = "İ"
a.downcase!(:turkic)
a.should == "i"
end
it "allows Lithuanian as an extra option" do
a = "İ"
a.downcase!(:turkic, :lithuanian)
a.should == "i"
end
it "does not allow any other additional option" do
lambda { a = "İ"; a.downcase!(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
a = "İS"
a.downcase!(:lithuanian)
a.should == "i\u{307}s"
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
a = "İS"
a.downcase!(:lithuanian, :turkic)
a.should == "is"
end
it "does not allow any other additional option" do
lambda { a = "İS"; a.downcase!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
describe "case folding" do
it "case folds special characters" do
a = "ß"
a.downcase!
a.should == "ß"
a.downcase!(:fold)
a.should == "ss"
end
end
it "does not allow invalid options" do
lambda { a = "ABC"; a.downcase!(:invalid_option) }.should raise_error(ArgumentError)
end
end end
it "returns nil if no modifications were made" do it "returns nil if no modifications were made" do

View file

@ -23,9 +23,62 @@ describe "String#swapcase" do
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "works for all of Unicode" do describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do
"äÖü".swapcase.should == "ÄöÜ" "äÖü".swapcase.should == "ÄöÜ"
end end
it "updates string metadata" do
swapcased = "Aßet".swapcase
swapcased.should == "aSSET"
swapcased.size.should == 5
swapcased.bytesize.should == 5
swapcased.ascii_only?.should be_true
end
end
describe "ASCII-only case mapping" do
it "does not swapcase non-ASCII characters" do
"aßet".swapcase(:ascii).should == "AßET"
end
end
describe "full Unicode case mapping adapted for Turkic languages" do
it "swaps case of ASCII characters according to Turkic semantics" do
"aiS".swapcase(:turkic).should == "Aİs"
end
it "allows Lithuanian as an extra option" do
"aiS".swapcase(:turkic, :lithuanian).should == "Aİs"
end
it "does not allow any other additional option" do
lambda { "aiS".swapcase(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
"".swapcase(:lithuanian).should == "iSS"
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
"iS".swapcase(:lithuanian, :turkic).should == "İs"
end
it "does not allow any other additional option" do
lambda { "aiS".swapcase(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
lambda { "abc".swapcase(:fold) }.should raise_error(ArgumentError)
end
it "does not allow invalid options" do
lambda { "abc".swapcase(:invalid_option) }.should raise_error(ArgumentError)
end
end end
it "returns subclass instances when called on a subclass" do it "returns subclass instances when called on a subclass" do
@ -42,11 +95,75 @@ describe "String#swapcase!" do
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "modifies self in place for all of Unicode" do describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
a = "äÖü" a = "äÖü"
a.swapcase!.should equal(a) a.swapcase!
a.should == "ÄöÜ" a.should == "ÄöÜ"
end end
it "updates string metadata" do
swapcased = "Aßet"
swapcased.swapcase!
swapcased.should == "aSSET"
swapcased.size.should == 5
swapcased.bytesize.should == 5
swapcased.ascii_only?.should be_true
end
end
describe "modifies self in place for ASCII-only case mapping" do
it "does not swapcase non-ASCII characters" do
a = "aßet"
a.swapcase!(:ascii)
a.should == "AßET"
end
end
describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do
it "swaps case of ASCII characters according to Turkic semantics" do
a = "aiS"
a.swapcase!(:turkic)
a.should == "Aİs"
end
it "allows Lithuanian as an extra option" do
a = "aiS"
a.swapcase!(:turkic, :lithuanian)
a.should == "Aİs"
end
it "does not allow any other additional option" do
lambda { a = "aiS"; a.swapcase!(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
a = ""
a.swapcase!(:lithuanian)
a.should == "iSS"
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
a = "iS"
a.swapcase!(:lithuanian, :turkic)
a.should == "İs"
end
it "does not allow any other additional option" do
lambda { a = "aiS"; a.swapcase!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
lambda { a = "abc"; a.swapcase!(:fold) }.should raise_error(ArgumentError)
end
it "does not allow invalid options" do
lambda { a = "abc"; a.swapcase!(:invalid_option) }.should raise_error(ArgumentError)
end
end end
it "returns nil if no modifications were made" do it "returns nil if no modifications were made" do

View file

@ -23,9 +23,62 @@ describe "String#upcase" do
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "works for all of Unicode" do describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do
"äöü".upcase.should == "ÄÖÜ" "äöü".upcase.should == "ÄÖÜ"
end end
it "updates string metadata" do
upcased = "aßet".upcase
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
upcased.ascii_only?.should be_true
end
end
describe "ASCII-only case mapping" do
it "does not upcase non-ASCII characters" do
"aßet".upcase(:ascii).should == "AßET"
end
end
describe "full Unicode case mapping adapted for Turkic languages" do
it "upcases ASCII characters according to Turkic semantics" do
"i".upcase(:turkic).should == "İ"
end
it "allows Lithuanian as an extra option" do
"i".upcase(:turkic, :lithuanian).should == "İ"
end
it "does not allow any other additional option" do
lambda { "i".upcase(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
"".upcase(:lithuanian).should == "ISS"
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
"".upcase(:lithuanian, :turkic).should == "İSS"
end
it "does not allow any other additional option" do
lambda { "".upcase(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
lambda { "abc".upcase(:fold) }.should raise_error(ArgumentError)
end
it "does not allow invalid options" do
lambda { "abc".upcase(:invalid_option) }.should raise_error(ArgumentError)
end
end end
it "taints result when self is tainted" do it "taints result when self is tainted" do
@ -46,13 +99,76 @@ describe "String#upcase!" do
a.should == "HELLO" a.should == "HELLO"
end end
ruby_version_is '2.4' do ruby_version_is '2.4' do
it "modifies self in place for all of Unicode" do describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
a = "äöü" a = "äöü"
a.upcase!.should equal(a) a.upcase!
a.should == "ÄÖÜ" a.should == "ÄÖÜ"
end end
it "updates string metadata for self" do
upcased = "aßet"
upcased.upcase!
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
upcased.ascii_only?.should be_true
end
end
describe "modifies self in place for ASCII-only case mapping" do
it "does not upcase non-ASCII characters" do
a = "aßet"
a.upcase!(:ascii)
a.should == "AßET"
end
end
describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do
it "upcases ASCII characters according to Turkic semantics" do
a = "i"
a.upcase!(:turkic)
a.should == "İ"
end
it "allows Lithuanian as an extra option" do
a = "i"
a.upcase!(:turkic, :lithuanian)
a.should == "İ"
end
it "does not allow any other additional option" do
lambda { a = "i"; a.upcase!(:turkic, :ascii) }.should raise_error(ArgumentError)
end
end
describe "modifies self in place for full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
a = ""
a.upcase!(:lithuanian)
a.should == "ISS"
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
a = ""
a.upcase!(:lithuanian, :turkic)
a.should == "İSS"
end
it "does not allow any other additional option" do
lambda { a = ""; a.upcase!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
lambda { a = "abc"; a.upcase!(:fold) }.should raise_error(ArgumentError)
end
it "does not allow invalid options" do
lambda { a = "abc"; a.upcase!(:invalid_option) }.should raise_error(ArgumentError)
end
end end
it "returns nil if no modifications were made" do it "returns nil if no modifications were made" do

View file

@ -45,6 +45,16 @@ describe "Time#<=>" do
(Time.at(100, 0) <=> Time.at(100, Rational(1,1000))).should == -1 (Time.at(100, 0) <=> Time.at(100, Rational(1,1000))).should == -1
end end
it "returns nil when compared to an Integer because Time does not respond to #coerce" do
time = Time.at(1)
time.respond_to?(:coerce).should == false
time.should_receive(:respond_to?).exactly(2).and_return(false)
-> {
(time <=> 2).should == nil
(2 <=> time).should == nil
}.should_not complain
end
describe "given a non-Time argument" do describe "given a non-Time argument" do
it "returns nil if argument <=> self returns nil" do it "returns nil if argument <=> self returns nil" do
t = Time.now t = Time.now

View file

@ -198,10 +198,18 @@ describe "Invoking a method" do
lambda { no_such_method }.should raise_error NameError lambda { no_such_method }.should raise_error NameError
end end
it "should omit the method_missing call from the backtrace for NameError" do
lambda { no_such_method }.should raise_error { |e| e.backtrace.first.should_not include("method_missing") }
end
it "raises NoMethodError if invoked as an unambiguous method call" do it "raises NoMethodError if invoked as an unambiguous method call" do
lambda { no_such_method() }.should raise_error NoMethodError lambda { no_such_method() }.should raise_error NoMethodError
lambda { no_such_method(1,2,3) }.should raise_error NoMethodError lambda { no_such_method(1,2,3) }.should raise_error NoMethodError
end end
it "should omit the method_missing call from the backtrace for NoMethodError" do
lambda { no_such_method() }.should raise_error { |e| e.backtrace.first.should_not include("method_missing") }
end
end end
end end

View file

@ -95,6 +95,12 @@ describe "C-API Class function" do
obj.call_super_method.should == :super_method obj.call_super_method.should == :super_method
end end
it "calls the method in the superclass with the correct self" do
@s.define_call_super_method CApiClassSpecs::SubSelf, "call_super_method"
obj = CApiClassSpecs::SubSelf.new
obj.call_super_method.should equal obj
end
it "calls the method in the superclass through two native levels" do it "calls the method in the superclass through two native levels" do
@s.define_call_super_method CApiClassSpecs::Sub, "call_super_method" @s.define_call_super_method CApiClassSpecs::Sub, "call_super_method"
@s.define_call_super_method CApiClassSpecs::SubSub, "call_super_method" @s.define_call_super_method CApiClassSpecs::SubSub, "call_super_method"

View file

@ -12,6 +12,19 @@
extern "C" { extern "C" {
#endif #endif
/* Make sure the RSTRING_PTR and the bytes are in native memory.
* On TruffleRuby RSTRING_PTR and the bytes remain in managed memory
* until they must be written to native memory.
* In some specs we want to test using the native memory. */
char* NATIVE_RSTRING_PTR(VALUE str) {
char* ptr = RSTRING_PTR(str);
char** native = malloc(sizeof(char*));
*native = ptr;
ptr = *native;
free(native);
return ptr;
}
#ifdef HAVE_RB_CSTR2INUM #ifdef HAVE_RB_CSTR2INUM
VALUE string_spec_rb_cstr2inum(VALUE self, VALUE str, VALUE inum) { VALUE string_spec_rb_cstr2inum(VALUE self, VALUE str, VALUE inum) {
int num = FIX2INT(inum); int num = FIX2INT(inum);
@ -65,6 +78,10 @@ VALUE string_spec_rb_str_buf_new(VALUE self, VALUE len, VALUE str) {
return buf; return buf;
} }
VALUE string_spec_rb_str_capacity(VALUE self, VALUE str) {
return SIZET2NUM(rb_str_capacity(str));
}
#endif #endif
#ifdef HAVE_RB_STR_BUF_NEW2 #ifdef HAVE_RB_STR_BUF_NEW2
@ -182,6 +199,10 @@ VALUE string_spec_rb_str_new(VALUE self, VALUE str, VALUE len) {
return rb_str_new(RSTRING_PTR(str), FIX2INT(len)); return rb_str_new(RSTRING_PTR(str), FIX2INT(len));
} }
VALUE string_spec_rb_str_new_native(VALUE self, VALUE str, VALUE len) {
return rb_str_new(NATIVE_RSTRING_PTR(str), FIX2INT(len));
}
VALUE string_spec_rb_str_new_offset(VALUE self, VALUE str, VALUE offset, VALUE len) { VALUE string_spec_rb_str_new_offset(VALUE self, VALUE str, VALUE offset, VALUE len) {
return rb_str_new(RSTRING_PTR(str) + FIX2INT(offset), FIX2INT(len)); return rb_str_new(RSTRING_PTR(str) + FIX2INT(offset), FIX2INT(len));
} }
@ -358,6 +379,11 @@ VALUE string_spec_RSTRING_PTR_assign(VALUE self, VALUE str, VALUE chr) {
return Qnil; return Qnil;
} }
VALUE string_spec_RSTRING_PTR_set(VALUE self, VALUE str, VALUE i, VALUE chr) {
RSTRING_PTR(str)[FIX2INT(i)] = (char) FIX2INT(chr);
return str;
}
VALUE string_spec_RSTRING_PTR_after_funcall(VALUE self, VALUE str, VALUE cb) { VALUE string_spec_RSTRING_PTR_after_funcall(VALUE self, VALUE str, VALUE cb) {
/* Silence gcc 4.3.2 warning about computed value not used */ /* Silence gcc 4.3.2 warning about computed value not used */
if(RSTRING_PTR(str)) { /* force it out */ if(RSTRING_PTR(str)) { /* force it out */
@ -366,6 +392,19 @@ VALUE string_spec_RSTRING_PTR_after_funcall(VALUE self, VALUE str, VALUE cb) {
return rb_str_new2(RSTRING_PTR(str)); return rb_str_new2(RSTRING_PTR(str));
} }
VALUE string_spec_RSTRING_PTR_after_yield(VALUE self, VALUE str) {
char* ptr = NATIVE_RSTRING_PTR(str);
long len = RSTRING_LEN(str);
VALUE from_rstring_ptr;
ptr[0] = '1';
rb_yield(str);
ptr[2] = '2';
from_rstring_ptr = rb_str_new(ptr, len);
return from_rstring_ptr;
}
#endif #endif
#ifdef HAVE_STRINGVALUE #ifdef HAVE_STRINGVALUE
@ -480,6 +519,7 @@ void Init_string_spec(void) {
#ifdef HAVE_RB_STR_BUF_NEW #ifdef HAVE_RB_STR_BUF_NEW
rb_define_method(cls, "rb_str_buf_new", string_spec_rb_str_buf_new, 2); rb_define_method(cls, "rb_str_buf_new", string_spec_rb_str_buf_new, 2);
rb_define_method(cls, "rb_str_capacity", string_spec_rb_str_capacity, 1);
#endif #endif
#ifdef HAVE_RB_STR_BUF_NEW2 #ifdef HAVE_RB_STR_BUF_NEW2
@ -540,6 +580,7 @@ void Init_string_spec(void) {
#ifdef HAVE_RB_STR_NEW #ifdef HAVE_RB_STR_NEW
rb_define_method(cls, "rb_str_new", string_spec_rb_str_new, 2); rb_define_method(cls, "rb_str_new", string_spec_rb_str_new, 2);
rb_define_method(cls, "rb_str_new_native", string_spec_rb_str_new_native, 2);
rb_define_method(cls, "rb_str_new_offset", string_spec_rb_str_new_offset, 3); rb_define_method(cls, "rb_str_new_offset", string_spec_rb_str_new_offset, 3);
#endif #endif
@ -643,8 +684,9 @@ void Init_string_spec(void) {
#ifdef HAVE_RSTRING_PTR #ifdef HAVE_RSTRING_PTR
rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1); rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1);
rb_define_method(cls, "RSTRING_PTR_assign", string_spec_RSTRING_PTR_assign, 2); rb_define_method(cls, "RSTRING_PTR_assign", string_spec_RSTRING_PTR_assign, 2);
rb_define_method(cls, "RSTRING_PTR_after_funcall", rb_define_method(cls, "RSTRING_PTR_set", string_spec_RSTRING_PTR_set, 3);
string_spec_RSTRING_PTR_after_funcall, 2); rb_define_method(cls, "RSTRING_PTR_after_funcall", string_spec_RSTRING_PTR_after_funcall, 2);
rb_define_method(cls, "RSTRING_PTR_after_yield", string_spec_RSTRING_PTR_after_yield, 1);
#endif #endif
#ifdef HAVE_STRINGVALUE #ifdef HAVE_STRINGVALUE

View file

@ -68,10 +68,19 @@ class CApiClassSpecs
class SubSub < Sub class SubSub < Sub
def call_super_method def call_super_method
:subclass_method :subsubclass_method
end end
end end
class SuperSelf
def call_super_method
self
end
end
class SubSelf < SuperSelf
end
class A class A
C = 1 C = 1
autoload :D, File.expand_path('../path_to_class.rb', __FILE__) autoload :D, File.expand_path('../path_to_class.rb', __FILE__)

View file

@ -48,14 +48,43 @@ describe "C-API String function" do
@s.rb_str_set_len(@str, 8).should == "abcde\x00gh" @s.rb_str_set_len(@str, 8).should == "abcde\x00gh"
end end
it "updates the byte size and character size" do
@s.rb_str_set_len(@str, 4)
@str.bytesize.should == 4
@str.size.should == 4
@str.should == "abcd"
end
it "updates the string's attributes visible in C code" do it "updates the string's attributes visible in C code" do
@s.rb_str_set_len_RSTRING_LEN(@str, 4).should == 4 @s.rb_str_set_len_RSTRING_LEN(@str, 4).should == 4
end end
it "can reveal characters written from C with RSTRING_PTR" do
@s.rb_str_set_len(@str, 1)
@str.should == "a"
@str.force_encoding(Encoding::UTF_8)
@s.RSTRING_PTR_set(@str, 1, 'B'.ord)
@s.RSTRING_PTR_set(@str, 2, 'C'.ord)
@s.rb_str_set_len(@str, 3)
@str.bytesize.should == 3
@str.should == "aBC"
end
end end
describe "rb_str_buf_new" do describe "rb_str_buf_new" do
it "returns the equivalent of an empty string" do it "returns the equivalent of an empty string" do
@s.rb_str_buf_new(10, nil).should == "" buf = @s.rb_str_buf_new(10, nil)
buf.should == ""
buf.bytesize.should == 0
buf.size.should == 0
@s.RSTRING_LEN(buf).should == 0
end
it "returns a string with the given capacity" do
buf = @s.rb_str_buf_new(256, nil)
@s.rb_str_capacity(buf).should == 256
end end
it "returns a string that can be appended to" do it "returns a string that can be appended to" do
@ -83,6 +112,19 @@ describe "C-API String function" do
str[0, 6].should == "abcd\x00f" str[0, 6].should == "abcd\x00f"
@s.RSTRING_LEN(str).should == 8 @s.RSTRING_LEN(str).should == 8
end end
it "can be used as a general buffer and reveal characters with rb_str_set_len" do
str = @s.rb_str_buf_new(10, "abcdef")
@s.RSTRING_PTR_set(str, 0, 195)
@s.RSTRING_PTR_set(str, 1, 169)
@s.rb_str_set_len(str, 2)
str.force_encoding(Encoding::UTF_8)
str.bytesize.should == 2
str.size.should == 1
str.should == "é"
end
end end
describe "rb_str_buf_new2" do describe "rb_str_buf_new2" do
@ -93,6 +135,10 @@ describe "C-API String function" do
end end
describe "rb_str_new" do describe "rb_str_new" do
it "creates a new String with ASCII-8BIT Encoding" do
@s.rb_str_new("", 0).encoding.should == Encoding::ASCII_8BIT
end
it "returns a new string object from a char buffer of len characters" do it "returns a new string object from a char buffer of len characters" do
@s.rb_str_new("hello", 3).should == "hel" @s.rb_str_new("hello", 3).should == "hel"
end end
@ -101,6 +147,11 @@ describe "C-API String function" do
@s.rb_str_new("hello", 0).should == "" @s.rb_str_new("hello", 0).should == ""
end end
it "copy length bytes and does not stop at the first \\0 byte" do
@s.rb_str_new("he\x00llo", 6).should == "he\x00llo"
@s.rb_str_new_native("he\x00llo", 6).should == "he\x00llo"
end
it "returns a string from an offset char buffer" do it "returns a string from an offset char buffer" do
@s.rb_str_new_offset("hello", 1, 3).should == "ell" @s.rb_str_new_offset("hello", 1, 3).should == "ell"
end end
@ -110,12 +161,6 @@ describe "C-API String function" do
it_behaves_like :rb_str_new2, :rb_str_new2 it_behaves_like :rb_str_new2, :rb_str_new2
end end
describe "rb_str_new" do
it "creates a new String with ASCII-8BIT Encoding" do
@s.rb_str_new("", 0).encoding.should == Encoding::ASCII_8BIT
end
end
describe "rb_str_new_cstr" do describe "rb_str_new_cstr" do
it_behaves_like :rb_str_new2, :rb_str_new_cstr it_behaves_like :rb_str_new2, :rb_str_new_cstr
end end
@ -402,7 +447,7 @@ describe "C-API String function" do
it "allows changing the characters in the string" do it "allows changing the characters in the string" do
str = "abc" str = "abc"
@s.RSTRING_PTR_assign(str, 65) @s.RSTRING_PTR_assign(str, 'A'.ord)
str.should == "AAA" str.should == "AAA"
end end
@ -417,6 +462,13 @@ describe "C-API String function" do
ret.should == str ret.should == str
end end
it "reflects changes from native memory and from String#setbyte in bounds" do
str = "abc"
from_rstring_ptr = @s.RSTRING_PTR_after_yield(str) { str.setbyte(1, 'B'.ord) }
from_rstring_ptr.should == "1B2"
str.should == "1B2"
end
it "returns a pointer to the contents of encoded pointer-sized string" do it "returns a pointer to the contents of encoded pointer-sized string" do
s = "70パク". s = "70パク".
encode(Encoding::UTF_16LE). encode(Encoding::UTF_16LE).