1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65388 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2018-10-27 10:48:40 +00:00
parent ecc707e233
commit 3e6337b88b
69 changed files with 742 additions and 141 deletions

View file

@ -6,15 +6,15 @@ script:
- ../mspec/bin/mspec $MSPEC_OPTS
matrix:
include:
- rvm: 2.5.1
- rvm: 2.5.3
env: MSPEC_OPTS="-R2 -ff"
- rvm: 2.3.7
- rvm: 2.4.4
- rvm: 2.5.1
- rvm: 2.3.8
- rvm: 2.4.5
- rvm: 2.5.3
env: CHECK_LEAKS=true
- rvm: ruby-head
- env: RUBOCOP=true
rvm: 2.4.4
rvm: 2.4.5
script:
- gem install rubocop -v 0.54.0
- rubocop

View file

@ -6,14 +6,14 @@ describe "Array#eql?" do
it_behaves_like :array_eql, :eql?
it "returns false if any corresponding elements are not #eql?" do
[1, 2, 3, 4].send(@method, [1, 2, 3, 4.0]).should be_false
[1, 2, 3, 4].should_not eql([1, 2, 3, 4.0])
end
it "returns false if other is not a kind of Array" do
obj = mock("array eql?")
obj.should_not_receive(:to_ary)
obj.should_not_receive(@method)
obj.should_not_receive(:eql?)
[1, 2, 3].send(@method, obj).should be_false
[1, 2, 3].should_not eql(obj)
end
end

View file

@ -2,9 +2,10 @@ class Object
# This helper is defined here rather than in MSpec because
# it is only used in #pack specs.
def pack_format(count=nil, repeat=nil)
format = "#{instance_variable_get(:@method)}#{count}"
format = instance_variable_get(:@method)
format += count.to_s unless format == 'P' || format == 'p'
format *= repeat if repeat
format
format.dup # because it may then become tainted
end
end

View file

@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
require_relative 'shared/taint'
describe "Array#pack with format 'A'" do
it_behaves_like :array_pack_basic, 'A'
it_behaves_like :array_pack_basic_non_float, 'A'
it_behaves_like :array_pack_no_platform, 'A'
it_behaves_like :array_pack_string, 'A'
it_behaves_like :array_pack_taint, 'A'
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("A*").should == "abc"
@ -36,6 +38,7 @@ describe "Array#pack with format 'a'" do
it_behaves_like :array_pack_basic_non_float, 'a'
it_behaves_like :array_pack_no_platform, 'a'
it_behaves_like :array_pack_string, 'a'
it_behaves_like :array_pack_taint, 'a'
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("a*").should == "abc"

View file

@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/encodings'
require_relative 'shared/taint'
describe "Array#pack with format 'B'" do
it_behaves_like :array_pack_basic, 'B'
it_behaves_like :array_pack_basic_non_float, 'B'
it_behaves_like :array_pack_arguments, 'B'
it_behaves_like :array_pack_hex, 'B'
it_behaves_like :array_pack_taint, 'B'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
@ -59,6 +61,7 @@ describe "Array#pack with format 'b'" do
it_behaves_like :array_pack_basic_non_float, 'b'
it_behaves_like :array_pack_arguments, 'b'
it_behaves_like :array_pack_hex, 'b'
it_behaves_like :array_pack_taint, 'b'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")

View file

@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/encodings'
require_relative 'shared/taint'
describe "Array#pack with format 'H'" do
it_behaves_like :array_pack_basic, 'H'
it_behaves_like :array_pack_basic_non_float, 'H'
it_behaves_like :array_pack_arguments, 'H'
it_behaves_like :array_pack_hex, 'H'
it_behaves_like :array_pack_taint, 'H'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
@ -105,6 +107,7 @@ describe "Array#pack with format 'h'" do
it_behaves_like :array_pack_basic_non_float, 'h'
it_behaves_like :array_pack_arguments, 'h'
it_behaves_like :array_pack_hex, 'h'
it_behaves_like :array_pack_taint, 'h'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")

View file

@ -2,11 +2,13 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'
describe "Array#pack with format 'M'" do
it_behaves_like :array_pack_basic, 'M'
it_behaves_like :array_pack_basic_non_float, 'M'
it_behaves_like :array_pack_arguments, 'M'
it_behaves_like :array_pack_taint, 'M'
it "encodes an empty string as an empty string" do
[""].pack("M").should == ""
@ -192,6 +194,7 @@ describe "Array#pack with format 'm'" do
it_behaves_like :array_pack_basic, 'm'
it_behaves_like :array_pack_basic_non_float, 'm'
it_behaves_like :array_pack_arguments, 'm'
it_behaves_like :array_pack_taint, 'm'
it "encodes an empty string as an empty string" do
[""].pack("m").should == ""

View file

@ -1,11 +1,58 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'
describe "Array#pack with format 'P'" do
it_behaves_like :array_pack_basic_non_float, 'P'
it_behaves_like :array_pack_taint, 'P'
it "produces as many bytes as there are in a pointer" do
["hello"].pack("P").size.should == [0].pack("J").size
end
it "round-trips a string through pack and unpack" do
["hello"].pack("P").unpack("P5").should == ["hello"]
end
it "taints the input string" do
input_string = "hello"
[input_string].pack("P")
input_string.tainted?.should be_true
end
it "does not taint the output string in normal cases" do
["hello"].pack("P").tainted?.should be_false
end
it "with nil gives a null pointer" do
[nil].pack("P").unpack("J").should == [0]
end
end
describe "Array#pack with format 'p'" do
it_behaves_like :array_pack_basic_non_float, 'p'
it_behaves_like :array_pack_taint, 'p'
it "produces as many bytes as there are in a pointer" do
["hello"].pack("p").size.should == [0].pack("J").size
end
it "round-trips a string through pack and unpack" do
["hello"].pack("p").unpack("p").should == ["hello"]
end
it "taints the input string" do
input_string = "hello"
[input_string].pack("p")
input_string.tainted?.should be_true
end
it "does not taint the output string in normal cases" do
["hello"].pack("p").tainted?.should be_false
end
it "with nil gives a null pointer" do
[nil].pack("p").unpack("J").should == [0]
end
end

View file

@ -36,38 +36,6 @@ describe :array_pack_string, shared: true do
lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
end
it "returns a tainted string when a pack argument is tainted" do
["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true
end
it "does not return a tainted string when the array is tainted" do
["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false
end
it "returns a tainted string when the format is tainted" do
["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true
end
it "returns a tainted string when an empty format is tainted" do
["abcd", 0x20].pack("".taint).tainted?.should be_true
end
it "returns a untrusted string when the format is untrusted" do
["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true
end
it "returns a untrusted string when the empty format is untrusted" do
["abcd", 0x20].pack("".untrust).untrusted?.should be_true
end
it "returns a untrusted string when a pack argument is untrusted" do
["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true
end
it "returns a trusted string when the array is untrusted" do
["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false
end
it "returns a string in encoding of common to the concatenated results" do
f = pack_format("*")
[ [["\u{3042 3044 3046 3048}", 0x2000B].pack(f+"U"), Encoding::ASCII_8BIT],

View file

@ -0,0 +1,33 @@
describe :array_pack_taint, shared: true do
it "returns a tainted string when a pack argument is tainted" do
["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true
end
it "does not return a tainted string when the array is tainted" do
["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false
end
it "returns a tainted string when the format is tainted" do
["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true
end
it "returns a tainted string when an empty format is tainted" do
["abcd", 0x20].pack("".taint).tainted?.should be_true
end
it "returns a untrusted string when the format is untrusted" do
["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true
end
it "returns a untrusted string when the empty format is untrusted" do
["abcd", 0x20].pack("".untrust).untrusted?.should be_true
end
it "returns a untrusted string when a pack argument is untrusted" do
["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true
end
it "returns a trusted string when the array is untrusted" do
["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false
end
end

View file

@ -3,6 +3,7 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/unicode'
require_relative 'shared/taint'
describe "Array#pack with format 'U'" do
it_behaves_like :array_pack_basic, 'U'
@ -15,6 +16,7 @@ describe "Array#pack with format 'u'" do
it_behaves_like :array_pack_basic, 'u'
it_behaves_like :array_pack_basic_non_float, 'u'
it_behaves_like :array_pack_arguments, 'u'
it_behaves_like :array_pack_taint, 'u'
it "encodes an empty string as an empty string" do
[""].pack("u").should == ""

View file

@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
require_relative 'shared/taint'
describe "Array#pack with format 'Z'" do
it_behaves_like :array_pack_basic, 'Z'
it_behaves_like :array_pack_basic_non_float, 'Z'
it_behaves_like :array_pack_no_platform, 'Z'
it_behaves_like :array_pack_string, 'Z'
it_behaves_like :array_pack_taint, 'Z'
it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do
["abc"].pack("Z*").should == "abc\x00"

View file

@ -68,7 +68,6 @@ describe "Enumerable#all?" do
end
it "gathers whole arrays as elements when each yields multiple" do
# This spec doesn't spec what it says it does
multi = EnumerableSpecs::YieldsMultiWithFalse.new
multi.all?.should be_true
end

View file

@ -51,7 +51,6 @@ describe "Enumerable#none?" do
end
it "gathers whole arrays as elements when each yields multiple" do
# This spec doesn't spec what it says it does
multi = EnumerableSpecs::YieldsMultiWithFalse.new
multi.none?.should be_false
end

View file

@ -78,7 +78,6 @@ describe "Enumerable#one?" do
end
it "gathers initial args as elements when each yields multiple" do
# This spec doesn't spec what it says it does
multi = EnumerableSpecs::YieldsMulti.new
yielded = []
multi.one? { |e| yielded << e; false }.should == false

View file

@ -6,10 +6,11 @@ ruby_version_is "2.5" do
@hash = { a: 1, b: 2, c: 3 }
end
it "returns new hash" do
it "returns a new empty hash without arguments" do
ret = @hash.slice
ret.should_not equal(@hash)
ret.should be_an_instance_of(Hash)
ret.should == {}
end
it "returns the requested subset" do
@ -27,10 +28,28 @@ ruby_version_is "2.5" do
it "returns a Hash instance, even on subclasses" do
klass = Class.new(Hash)
h = klass.new
h[:bar] = 12
h[:foo] = 42
r = h.slice(:foo)
r.should == {foo: 42}
r.class.should == Hash
end
it "uses the regular Hash#[] method, even on subclasses that override it" do
ScratchPad.record []
klass = Class.new(Hash) do
def [](value)
ScratchPad << :used_subclassed_operator
super
end
end
h = klass.new
h[:bar] = 12
h[:foo] = 42
h.slice(:foo)
ScratchPad.recorded.should == []
end
end
end

View file

@ -0,0 +1,52 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
ruby_version_is "2.5" do
platform_is_not :windows do
describe "IO#pread" do
before :each do
@fname = tmp("io_pread.txt")
@contents = "1234567890"
touch(@fname) { |f| f.write @contents }
@file = File.open(@fname, "r+")
end
after :each do
@file.close
rm_r @fname
end
it "accepts a length, and an offset" do
@file.pread(4, 0).should == "1234"
@file.pread(3, 4).should == "567"
end
it "accepts a length, an offset, and an output buffer" do
buffer = "foo"
@file.pread(3, 4, buffer)
buffer.should == "567"
end
it "does not advance the file pointer" do
@file.pread(4, 0).should == "1234"
@file.read.should == "1234567890"
end
it "raises EOFError if end-of-file is reached" do
lambda { @file.pread(1, 10) }.should raise_error(EOFError)
end
it "raises IOError when file is not open in read mode" do
File.open(@fname, "w") do |file|
lambda { file.pread(1, 1) }.should raise_error(IOError)
end
end
it "raises IOError when file is closed" do
file = File.open(@fname, "r+")
file.close
lambda { file.pread(1, 1) }.should raise_error(IOError)
end
end
end
end

View file

@ -0,0 +1,45 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
ruby_version_is "2.5" do
platform_is_not :windows do
describe "IO#pwrite" do
before :each do
@fname = tmp("io_pwrite.txt")
@file = File.open(@fname, "w+")
end
after :each do
@file.close
rm_r @fname
end
it "returns the number of bytes written" do
@file.pwrite("foo", 0).should == 3
end
it "accepts a string and an offset" do
@file.pwrite("foo", 2)
@file.pread(3, 2).should == "foo"
end
it "does not advance the pointer in the file" do
@file.pwrite("bar", 3)
@file.write("foo")
@file.pread(6, 0).should == "foobar"
end
it "raises IOError when file is not open in write mode" do
File.open(@fname, "r") do |file|
lambda { file.pwrite("foo", 1) }.should raise_error(IOError)
end
end
it "raises IOError when file is closed" do
file = File.open(@fname, "w+")
file.close
lambda { file.pwrite("foo", 1) }.should raise_error(IOError)
end
end
end
end

View file

@ -127,6 +127,17 @@ end
describe "IO#write" do
it_behaves_like :io_write, :write
ruby_version_is "2.5" do
it "accepts multiple arguments" do
IO.pipe do |r, w|
w.write("foo", "bar")
w.close
r.read.should == "foobar"
end
end
end
end
platform_is :windows do

View file

@ -126,8 +126,8 @@ describe "Kernel.Complex()" do
describe "when passed a non-Numeric second argument" do
it "raises TypeError" do
lambda { Complex.send(@method, :sym, :sym) }.should raise_error(TypeError)
lambda { Complex.send(@method, 0, :sym) }.should raise_error(TypeError)
lambda { Complex(:sym, :sym) }.should raise_error(TypeError)
lambda { Complex(0, :sym) }.should raise_error(TypeError)
end
end

View file

@ -68,6 +68,7 @@ module KernelSpecs
module SomeOtherModule; end
module AncestorModule; end
module MyModule; end
module MyPrependedModule; end
module MyExtensionModule; end
class AncestorClass < String
@ -80,6 +81,8 @@ module KernelSpecs
class KindaClass < AncestorClass
include MyModule
prepend MyPrependedModule
def initialize
self.extend MyExtensionModule
end

View file

@ -31,7 +31,11 @@ describe :kernel_kind_of, shared: true do
@o.send(@method, KernelSpecs::MyExtensionModule).should == true
end
it "returns false if given a Module not included in object's class nor ancestors" do
it "returns true if given a Module that object has been prepended with" do
@o.send(@method, KernelSpecs::MyPrependedModule).should == true
end
it "returns false if given a Module not included nor prepended in object's class nor ancestors" do
@o.send(@method, KernelSpecs::SomeOtherModule).should == false
end
@ -41,4 +45,11 @@ describe :kernel_kind_of, shared: true do
lambda { @o.send(@method, :KindaClass) }.should raise_error(TypeError)
lambda { @o.send(@method, Object.new) }.should raise_error(TypeError)
end
it "does not take into account `class` method overriding" do
def @o.class; Integer; end
@o.send(@method, Integer).should == false
@o.send(@method, KernelSpecs::KindaClass).should == true
end
end

View file

@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/call'
require_relative 'shared/call_arguments'
require_relative 'fixtures/proc_aref'
require_relative 'fixtures/proc_aref_frozen'
describe "Proc#[]" do
it_behaves_like :proc_call, :[]
@ -14,3 +16,14 @@ end
describe "Proc#call on a Proc created with Kernel#lambda or Kernel#proc" do
it_behaves_like :proc_call_on_proc_or_lambda, :call
end
ruby_bug "#15118", ""..."2.6" do
describe "Proc#[] with frozen_string_literals" do
it "doesn't duplicate frozen strings" do
ProcArefSpecs.aref.frozen?.should be_false
ProcArefSpecs.aref_freeze.frozen?.should be_true
ProcArefFrozenSpecs.aref.frozen?.should be_true
ProcArefFrozenSpecs.aref_freeze.frozen?.should be_true
end
end
end

View file

@ -0,0 +1,9 @@
module ProcArefSpecs
def self.aref
proc {|a| a }["sometext"]
end
def self.aref_freeze
proc {|a| a }["sometext".freeze]
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
module ProcArefFrozenSpecs
def self.aref
proc {|a| a }["sometext"]
end
def self.aref_freeze
proc {|a| a }["sometext".freeze]
end
end

View file

@ -3,18 +3,30 @@ describe :proc_to_s, shared: true do
it "returns a description optionally including file and line number" do
Proc.new { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:4)?>$/
end
it "has an ASCII-8BIT encoding" do
Proc.new { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT
end
end
describe "for a proc created with lambda" do
it "returns a description including '(lambda)' and optionally including file and line number" do
lambda { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:10)? \(lambda\)>$/
end
it "has an ASCII-8BIT encoding" do
lambda { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT
end
end
describe "for a proc created with proc" do
it "returns a description optionally including file and line number" do
proc { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:16)?>$/
end
it "has an ASCII-8BIT encoding" do
proc { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT
end
end
describe "for a proc created with UnboundMethod#to_proc" do
@ -23,5 +35,11 @@ describe :proc_to_s, shared: true do
method("hello").to_proc.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:22)? \(lambda\)>$/
end
it "has an ASCII-8BIT encoding" do
def hello; end
method("hello").to_proc.send(@method).encoding.should == Encoding::ASCII_8BIT
end
end
end

View file

@ -1,18 +1,9 @@
# -*- encoding: binary -*-
require_relative '../../spec_helper'
require_relative 'shared/bytes'
describe "Random#bytes" do
it "returns a String" do
Random.new.bytes(1).should be_an_instance_of(String)
end
it "returns a String of the length given as argument" do
Random.new.bytes(15).length.should == 15
end
it "returns an ASCII-8BIT String" do
Random.new.bytes(15).encoding.should == Encoding::ASCII_8BIT
end
it_behaves_like :random_bytes, :bytes, Random.new
it "returns the same output for a given seed" do
Random.new(33).bytes(2).should == Random.new(33).bytes(2)
@ -32,8 +23,10 @@ describe "Random#bytes" do
rnd.bytes(1000) # skip some
rnd.bytes(2).should == "\x17\x12"
end
end
it "returns a random binary String" do
Random.new.bytes(12).should_not == Random.new.bytes(12)
ruby_version_is "2.6" do
describe "Random.bytes" do
it_behaves_like :random_bytes, :bytes, Random
end
end

View file

@ -0,0 +1,17 @@
describe :random_bytes, shared: true do
it "returns a String" do
@object.bytes(1).should be_an_instance_of(String)
end
it "returns a String of the length given as argument" do
@object.bytes(15).length.should == 15
end
it "returns an ASCII-8BIT String" do
@object.bytes(15).encoding.should == Encoding::ASCII_8BIT
end
it "returns a random binary String" do
@object.bytes(12).should_not == @object.bytes(12)
end
end

View file

@ -5,6 +5,6 @@ describe "Range#eql?" do
it_behaves_like :range_eql, :eql?
it "returns false if the endpoints are not eql?" do
(0..1).send(@method, 0..1.0).should == false
(0..1).should_not eql(0..1.0)
end
end

View file

@ -5,6 +5,6 @@ describe "Range#==" do
it_behaves_like :range_eql, :==
it "returns true if the endpoints are ==" do
(0..1).send(@method, 0..1.0).should == true
(0..1).should == (0..1.0)
end
end

View file

@ -5,7 +5,6 @@ describe "String#chars" do
it_behaves_like :string_chars, :chars
it "returns an array when no block given" do
ary = "hello".send(@method)
ary.should == ['h', 'e', 'l', 'l', 'o']
"hello".chars.should == ['h', 'e', 'l', 'l', 'o']
end
end

View file

@ -8,13 +8,13 @@ with_feature :encoding do
it_behaves_like :string_codepoints, :codepoints
it "returns an Array when no block is given" do
"abc".send(@method).should == [?a.ord, ?b.ord, ?c.ord]
"abc".codepoints.should == [?a.ord, ?b.ord, ?c.ord]
end
it "raises an ArgumentError when no block is given if self has an invalid encoding" do
s = "\xDF".force_encoding(Encoding::UTF_8)
s.valid_encoding?.should be_false
lambda {s.send(@method)}.should raise_error(ArgumentError)
lambda { s.codepoints }.should raise_error(ArgumentError)
end
end
end

View file

@ -0,0 +1,11 @@
require_relative 'shared/chars'
require_relative 'shared/grapheme_clusters'
require_relative 'shared/each_char_without_block'
ruby_version_is "2.5" do
describe "String#each_grapheme_cluster" do
it_behaves_like :string_chars, :each_grapheme_cluster
it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster
it_behaves_like :string_each_char_without_block, :each_grapheme_cluster
end
end

View file

@ -4,7 +4,7 @@ class Object
def unpack_format(count=nil, repeat=nil)
format = "#{instance_variable_get(:@method)}#{count}"
format *= repeat if repeat
format
format.dup # because it may then become tainted
end
end

View file

@ -0,0 +1,15 @@
require_relative 'shared/chars'
require_relative 'shared/grapheme_clusters'
ruby_version_is "2.5" do
describe "String#grapheme_clusters" do
it_behaves_like :string_chars, :grapheme_clusters
it_behaves_like :string_grapheme_clusters, :grapheme_clusters
it "returns an array when no block given" do
string = "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}"
string.grapheme_clusters.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"]
end
end
end

View file

@ -7,7 +7,7 @@ describe "String#lines" do
it_behaves_like :string_each_line, :lines
it "returns an array when no block given" do
ary = "hello world".send(@method, ' ')
ary = "hello world".lines(' ')
ary.should == ["hello ", "world"]
end

View file

@ -19,6 +19,23 @@ describe "String#%" do
("%d%% %s" % [10, "of chickens!"]).should == "10% of chickens!"
end
describe "output's encoding" do
it "is the same as the format string if passed value is encoding-compatible" do
[Encoding::ASCII_8BIT, Encoding::US_ASCII, Encoding::UTF_8, Encoding::SHIFT_JIS].each do |encoding|
("hello %s!".encode(encoding) % "world").encoding.should == encoding
end
end
it "negotiates a compatible encoding if necessary" do
("hello %s" % 195.chr).encoding.should == Encoding::ASCII_8BIT
("hello %s".encode("shift_jis") % "wörld").encoding.should == Encoding::UTF_8
end
it "raises if a compatible encoding can't be found" do
lambda { "hello %s".encode("utf-8") % "world".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError)
end
end
ruby_version_is ""..."2.5" do
it "formats single % character at the end as literal %" do
("%" % []).should == "%"

View file

@ -0,0 +1,16 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
describe :string_grapheme_clusters, shared: true do
it "passes each grapheme cluster in self to the given block" do
a = []
# test string: abc[rainbow flag emoji][paw prints]
"ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}".send(@method) { |c| a << c }
a.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"]
end
it "returns self" do
s = StringSpecs::MyString.new "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}"
s.send(@method) {}.should equal(s)
end
end

View file

@ -75,9 +75,9 @@ describe "String#slice! with index" do
with_feature :encoding do
it "returns the character given by the character index" do
"hellö there".send(@method, 1).should == "e"
"hellö there".send(@method, 4).should == "ö"
"hellö there".send(@method, 6).should == "t"
"hellö there".slice!(1).should == "e"
"hellö there".slice!(4).should == "ö"
"hellö there".slice!(6).should == "t"
end
end
@ -151,15 +151,15 @@ describe "String#slice! with index, length" do
with_feature :encoding do
it "returns the substring given by the character offsets" do
"hellö there".send(@method, 1,0).should == ""
"hellö there".send(@method, 1,3).should == "ell"
"hellö there".send(@method, 1,6).should == "ellö t"
"hellö there".send(@method, 1,9).should == "ellö ther"
"hellö there".slice!(1,0).should == ""
"hellö there".slice!(1,3).should == "ell"
"hellö there".slice!(1,6).should == "ellö t"
"hellö there".slice!(1,9).should == "ellö ther"
end
it "treats invalid bytes as single bytes" do
xE6xCB = [0xE6,0xCB].pack('CC').force_encoding('utf-8')
"a#{xE6xCB}b".send(@method, 1, 2).should == xE6xCB
"a#{xE6xCB}b".slice!(1, 2).should == xE6xCB
end
end
end
@ -239,13 +239,13 @@ describe "String#slice! Range" do
with_feature :encoding do
it "returns the substring given by the character offsets of the range" do
"hellö there".send(@method, 1..1).should == "e"
"hellö there".send(@method, 1..3).should == "ell"
"hellö there".send(@method, 1...3).should == "el"
"hellö there".send(@method, -4..-2).should == "her"
"hellö there".send(@method, -4...-2).should == "he"
"hellö there".send(@method, 5..-1).should == " there"
"hellö there".send(@method, 5...-1).should == " ther"
"hellö there".slice!(1..1).should == "e"
"hellö there".slice!(1..3).should == "ell"
"hellö there".slice!(1...3).should == "el"
"hellö there".slice!(-4..-2).should == "her"
"hellö there".slice!(-4...-2).should == "he"
"hellö there".slice!(5..-1).should == " there"
"hellö there".slice!(5...-1).should == " ther"
end
end
@ -307,8 +307,8 @@ describe "String#slice! with Regexp" do
with_feature :encoding do
it "returns the matching portion of self with a multi byte character" do
"hëllo there".send(@method, /[ë](.)\1/).should == "ëll"
"".send(@method, //).should == ""
"hëllo there".slice!(/[ë](.)\1/).should == "ëll"
"".slice!(//).should == ""
end
end
@ -391,13 +391,13 @@ describe "String#slice! with Regexp, index" do
with_feature :encoding do
it "returns the encoding aware capture for the given index" do
"hår".send(@method, /(.)(.)(.)/, 0).should == "hår"
"hår".send(@method, /(.)(.)(.)/, 1).should == "h"
"hår".send(@method, /(.)(.)(.)/, 2).should == "å"
"hår".send(@method, /(.)(.)(.)/, 3).should == "r"
"hår".send(@method, /(.)(.)(.)/, -1).should == "r"
"hår".send(@method, /(.)(.)(.)/, -2).should == "å"
"hår".send(@method, /(.)(.)(.)/, -3).should == "h"
"hår".slice!(/(.)(.)(.)/, 0).should == "hår"
"hår".slice!(/(.)(.)(.)/, 1).should == "h"
"hår".slice!(/(.)(.)(.)/, 2).should == "å"
"hår".slice!(/(.)(.)(.)/, 3).should == "r"
"hår".slice!(/(.)(.)(.)/, -1).should == "r"
"hår".slice!(/(.)(.)(.)/, -2).should == "å"
"hår".slice!(/(.)(.)(.)/, -3).should == "h"
end
end

View file

@ -402,4 +402,14 @@ describe "String#split with Regexp" do
broken_str.force_encoding('utf-8')
lambda{ broken_str.split(/\r\n|\r|\n/) }.should raise_error(ArgumentError)
end
ruby_version_is "2.6" do
it "yields each split substrings if a block is given" do
a = []
returned_object = "chunky bacon".split(" ") { |str| a << str.capitalize }
returned_object.should == "chunky bacon"
a.should == ["Chunky", "Bacon"]
end
end
end

View file

@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
require_relative 'shared/taint'
describe "String#unpack with format 'A'" do
it_behaves_like :string_unpack_basic, 'A'
it_behaves_like :string_unpack_no_platform, 'A'
it_behaves_like :string_unpack_string, 'A'
it_behaves_like :string_unpack_Aa, 'A'
it_behaves_like :string_unpack_taint, 'A'
it "removes trailing space and NULL bytes from the decoded string" do
[ ["a\x00 b \x00", ["a\x00 b", ""]],
@ -40,6 +42,7 @@ describe "String#unpack with format 'a'" do
it_behaves_like :string_unpack_no_platform, 'a'
it_behaves_like :string_unpack_string, 'a'
it_behaves_like :string_unpack_Aa, 'a'
it_behaves_like :string_unpack_taint, 'a'
it "does not remove trailing whitespace or NULL bytes from the decoded string" do
[ ["a\x00 b \x00", ["a\x00 b \x00"]],

View file

@ -2,10 +2,12 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'
describe "String#unpack with format 'B'" do
it_behaves_like :string_unpack_basic, 'B'
it_behaves_like :string_unpack_no_platform, 'B'
it_behaves_like :string_unpack_taint, 'B'
it "decodes one bit from each byte for each format character starting with the most significant bit" do
[ ["\x00", "B", ["0"]],
@ -96,6 +98,7 @@ end
describe "String#unpack with format 'b'" do
it_behaves_like :string_unpack_basic, 'b'
it_behaves_like :string_unpack_no_platform, 'b'
it_behaves_like :string_unpack_taint, 'b'
it "decodes one bit from each byte for each format character starting with the least significant bit" do
[ ["\x00", "b", ["0"]],

View file

@ -2,10 +2,12 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'
describe "String#unpack with format 'H'" do
it_behaves_like :string_unpack_basic, 'H'
it_behaves_like :string_unpack_no_platform, 'H'
it_behaves_like :string_unpack_taint, 'H'
it "decodes one nibble from each byte for each format character starting with the most significant bit" do
[ ["\x8f", "H", ["8"]],
@ -66,6 +68,7 @@ end
describe "String#unpack with format 'h'" do
it_behaves_like :string_unpack_basic, 'h'
it_behaves_like :string_unpack_no_platform, 'h'
it_behaves_like :string_unpack_taint, 'h'
it "decodes one nibble from each byte for each format character starting with the least significant bit" do
[ ["\x8f", "h", ["f"]],

View file

@ -2,10 +2,12 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'
describe "String#unpack with format 'M'" do
it_behaves_like :string_unpack_basic, 'M'
it_behaves_like :string_unpack_no_platform, 'M'
it_behaves_like :string_unpack_taint, 'M'
it "decodes an empty string" do
"".unpack("M").should == [""]
@ -100,6 +102,7 @@ end
describe "String#unpack with format 'm'" do
it_behaves_like :string_unpack_basic, 'm'
it_behaves_like :string_unpack_no_platform, 'm'
it_behaves_like :string_unpack_taint, 'm'
it "decodes an empty string" do
"".unpack("m").should == [""]

View file

@ -1,21 +1,52 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'
describe "String#unpack with format 'P'" do
it_behaves_like :string_unpack_basic, 'P'
it_behaves_like :string_unpack_taint, 'P'
it "returns a random object after consuming a size-of a machine word bytes" do
str = "\0" * 1.size
str.unpack("P").should be_kind_of(Object)
it "round-trips a string through pack and unpack" do
["hello"].pack("P").unpack("P5").should == ["hello"]
end
it "cannot unpack a string except from the same object that created it, or a duplicate of it" do
packed = ["hello"].pack("P")
packed.unpack("P5").should == ["hello"]
packed.dup.unpack("P5").should == ["hello"]
lambda { packed.to_sym.to_s.unpack("P5") }.should raise_error(ArgumentError, /no associated pointer/)
end
it "taints the unpacked string" do
["hello"].pack("P").unpack("P5").first.tainted?.should be_true
end
it "reads as many characters as specified" do
["hello"].pack("P").unpack("P1").should == ["h"]
end
it "reads only as far as a NUL character" do
["hello"].pack("P").unpack("P10").should == ["hello"]
end
end
describe "String#unpack with format 'p'" do
it_behaves_like :string_unpack_basic, 'p'
it_behaves_like :string_unpack_taint, 'p'
it "returns a random object after consuming a size-of a machine word bytes" do
str = "\0" * 1.size
str.unpack("p").should be_kind_of(Object)
it "round-trips a string through pack and unpack" do
["hello"].pack("p").unpack("p").should == ["hello"]
end
it "cannot unpack a string except from the same object that created it, or a duplicate of it" do
packed = ["hello"].pack("p")
packed.unpack("p").should == ["hello"]
packed.dup.unpack("p").should == ["hello"]
lambda { packed.to_sym.to_s.unpack("p") }.should raise_error(ArgumentError, /no associated pointer/)
end
it "taints the unpacked string" do
["hello"].pack("p").unpack("p").first.tainted?.should be_true
end
end

View file

@ -0,0 +1,81 @@
describe :string_unpack_taint, shared: true do
it "does not taint returned arrays if given an untainted format string" do
"".unpack(unpack_format(2)).tainted?.should be_false
end
it "does not taint returned arrays if given a tainted format string" do
format_string = unpack_format(2).dup
format_string.taint
"".unpack(format_string).tainted?.should be_false
end
it "does not taint returned strings if given an untainted format string" do
"".unpack(unpack_format(2)).any?(&:tainted?).should be_false
end
it "does not taint returned strings if given a tainted format string" do
format_string = unpack_format(2).dup
format_string.taint
"".unpack(format_string).any?(&:tainted?).should be_false
end
it "does not taint returned arrays if given an untainted packed string" do
"".unpack(unpack_format(2)).tainted?.should be_false
end
it "does not taint returned arrays if given a tainted packed string" do
packed_string = ""
packed_string.taint
packed_string.unpack(unpack_format(2)).tainted?.should be_false
end
it "does not taint returned strings if given an untainted packed string" do
"".unpack(unpack_format(2)).any?(&:tainted?).should be_false
end
it "taints returned strings if given a tainted packed string" do
packed_string = ""
packed_string.taint
packed_string.unpack(unpack_format(2)).all?(&:tainted?).should be_true
end
it "does not untrust returned arrays if given an untrusted format string" do
"".unpack(unpack_format(2)).untrusted?.should be_false
end
it "does not untrust returned arrays if given a untrusted format string" do
format_string = unpack_format(2).dup
format_string.untrust
"".unpack(format_string).untrusted?.should be_false
end
it "does not untrust returned strings if given an untainted format string" do
"".unpack(unpack_format(2)).any?(&:untrusted?).should be_false
end
it "does not untrust returned strings if given a untrusted format string" do
format_string = unpack_format(2).dup
format_string.untrust
"".unpack(format_string).any?(&:untrusted?).should be_false
end
it "does not untrust returned arrays if given an trusted packed string" do
"".unpack(unpack_format(2)).untrusted?.should be_false
end
it "does not untrust returned arrays if given a untrusted packed string" do
packed_string = ""
packed_string.untrust
packed_string.unpack(unpack_format(2)).untrusted?.should be_false
end
it "does not untrust returned strings if given an trusted packed string" do
"".unpack(unpack_format(2)).any?(&:untrusted?).should be_false
end
it "untrusts returned strings if given a untrusted packed string" do
packed_string = ""
packed_string.untrust
packed_string.unpack(unpack_format(2)).all?(&:untrusted?).should be_true
end
end

View file

@ -3,11 +3,13 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/unicode'
require_relative 'shared/taint'
describe "String#unpack with format 'U'" do
it_behaves_like :string_unpack_basic, 'U'
it_behaves_like :string_unpack_no_platform, 'U'
it_behaves_like :string_unpack_unicode, 'U'
it_behaves_like :string_unpack_taint, 'U'
it "raises ArgumentError on a malformed byte sequence" do
lambda { "\xE3".unpack('U') }.should raise_error(ArgumentError)
@ -21,6 +23,7 @@ end
describe "String#unpack with format 'u'" do
it_behaves_like :string_unpack_basic, 'u'
it_behaves_like :string_unpack_no_platform, 'u'
it_behaves_like :string_unpack_taint, 'u'
it "decodes an empty string as an empty string" do
"".unpack("u").should == [""]

View file

@ -3,11 +3,13 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
require_relative 'shared/taint'
describe "String#unpack with format 'Z'" do
it_behaves_like :string_unpack_basic, 'Z'
it_behaves_like :string_unpack_no_platform, 'Z'
it_behaves_like :string_unpack_string, 'Z'
it_behaves_like :string_unpack_taint, 'Z'
it "stops decoding at NULL bytes when passed the '*' modifier" do
"a\x00\x00 b \x00c".unpack('Z*Z*Z*Z*').should == ["a", "", " b ", "c"]

View file

@ -8,6 +8,6 @@ describe "Struct#eql?" do
it "returns false if any corresponding elements are not #eql?" do
car = StructClasses::Car.new("Honda", "Accord", 1998)
similar_car = StructClasses::Car.new("Honda", "Accord", 1998.0)
car.send(@method, similar_car).should be_false
car.should_not eql(similar_car)
end
end

View file

@ -56,7 +56,7 @@ describe 'Thread::Backtrace::Location#path' do
end
context 'when the script is outside of the working directory' do
before do
before :each do
@parent_dir = tmp('path_outside_pwd')
@sub_dir = File.join(@parent_dir, 'sub')
@script = File.join(@parent_dir, 'main.rb')
@ -67,9 +67,7 @@ describe 'Thread::Backtrace::Location#path' do
cp(source, @script)
end
after do
rm_r(@script)
rm_r(@sub_dir)
after :each do
rm_r(@parent_dir)
end

View file

@ -49,6 +49,14 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10").utc_offset.should == -15000
end
it "returns a Time with a UTC offset specified as +HH:MM:SS" do
Time.new(2000, 1, 1, 0, 0, 0, "+05:30:37").utc_offset.should == 19837
end
it "returns a Time with a UTC offset specified as -HH:MM" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043
end
describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do
o = mock('string')
@ -96,6 +104,14 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, 86400 - 1).utc_offset.should == (86400 - 1)
lambda { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should raise_error(ArgumentError)
end
it "raises ArgumentError if the seconds argument is negative" do
lambda { Time.new(2000, 1, 1, 0, 0, -1) }.should raise_error(ArgumentError)
end
it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do
lambda { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError)
end
end
ruby_version_is "2.6" do

View file

@ -46,4 +46,8 @@ describe "Regexps with back-references" do
it "resets nested \<n> backreference before match of outer subexpression" do
/(a\1?){2}/.match("aaaa").to_a.should == ["aa", "a"]
end
it "can match an optional quote, followed by content, followed by a matching quote, as the whole string" do
/^("|)(.*)\1$/.match('x').to_a.should == ["x", "", "x"]
end
end

View file

@ -167,4 +167,31 @@ describe "Literal Regexps" do
pattern.to_s.should == ref
end
end
ruby_version_is '2.4' do
it "support handling unicode 9.0 characters with POSIX bracket expressions" do
char_lowercase = "\u{104D8}" # OSAGE SMALL LETTER A
/[[:lower:]]/.match(char_lowercase).to_s.should == char_lowercase
char_uppercase = "\u{104B0}" # OSAGE CAPITAL LETTER A
/[[:upper:]]/.match(char_uppercase).to_s.should == char_uppercase
end
end
ruby_version_is ""..."2.4" do
it "does not support handling unicode 9.0 characters with POSIX bracket expressions" do
char_lowercase = "\u{104D8}" # OSAGE SMALL LETTER A
/[[:lower:]]/.match(char_lowercase).should == nil
char_uppercase = "\u{104B0}" # OSAGE CAPITAL LETTER A
/[[:upper:]]/.match(char_lowercase).should == nil
end
it "supports handling unicode 8.0 characters with POSIX bracket expressions" do
char_lowercase = "\u{A7B5}" # LATIN SMALL LETTER BETA
/[[:lower:]]/.match(char_lowercase).to_s.should == char_lowercase
char_uppercase = "\u{A7B4}" # LATIN CAPITAL LETTER BETA
/[[:upper:]]/.match(char_uppercase).to_s.should == char_uppercase
end
end
end

View file

@ -38,9 +38,9 @@ describe "BigDecimal#mod_part_of_divmod" do
it "raises ZeroDivisionError if other is zero" do
bd5667 = BigDecimal("5667.19")
lambda { bd5667.send(@method, 0) }.should raise_error(ZeroDivisionError)
lambda { bd5667.send(@method, BigDecimal("0")) }.should raise_error(ZeroDivisionError)
lambda { @zero.send(@method, @zero) }.should raise_error(ZeroDivisionError)
lambda { bd5667.mod_part_of_divmod(0) }.should raise_error(ZeroDivisionError)
lambda { bd5667.mod_part_of_divmod(BigDecimal("0")) }.should raise_error(ZeroDivisionError)
lambda { @zero.mod_part_of_divmod(@zero) }.should raise_error(ZeroDivisionError)
end
end

View file

@ -15,8 +15,16 @@ describe "BigDecimal#to_s" do
@bigneg.to_s.kind_of?(String).should == true
end
ruby_version_is ''...'2.4' do
it "the default format looks like 0.xxxxEnn" do
@bigdec.to_s.should =~ /^0\.[0-9]*E[0-9]*$/i
@bigdec.to_s.should =~ /^0\.[0-9]*E[0-9]*$/
end
end
ruby_version_is '2.4' do
it "the default format looks like 0.xxxxenn" do
@bigdec.to_s.should =~ /^0\.[0-9]*e[0-9]*$/
end
end
it "takes an optional argument" do
@ -63,10 +71,12 @@ describe "BigDecimal#to_s" do
end
it "can use conventional floating point notation" do
@bigdec.to_s("F").should == @bigdec_str
@bigneg.to_s("F").should == @bigneg_str
%w[f F].each do |format_char|
@bigdec.to_s(format_char).should == @bigdec_str
@bigneg.to_s(format_char).should == @bigneg_str
str2 = "+123.45678901 23456789"
BigDecimal('123.45678901234567890').to_s('+8F').should == str2
BigDecimal('123.45678901234567890').to_s("+8#{format_char}").should == str2
end
end
end

View file

@ -0,0 +1,9 @@
require_relative '../../spec_helper'
require 'date'
describe "DateTime#+" do
it "is able to add sub-millisecond precision values" do
datetime = DateTime.new(2017)
(datetime + 0.00001).to_time.usec.should == 864000
end
end

View file

@ -0,0 +1,9 @@
require_relative '../../spec_helper'
require 'date'
describe "DateTime#-" do
it "is able to subtract sub-millisecond precision values" do
date = DateTime.new(2017)
((date + 0.00001) - date).should == Rational(1, 100000)
end
end

View file

@ -19,7 +19,7 @@ describe "UNIXSocket.open" do
end
it "opens a unix socket on the specified file and yields it to the block" do
UNIXSocket.send(@method, @path) do |client|
UNIXSocket.open(@path) do |client|
client.addr[0].should == "AF_UNIX"
client.closed?.should == false
end

View file

@ -8,9 +8,9 @@ describe "StringIO#getbyte" do
it "returns the 8-bit byte at the current position" do
io = StringIO.new("example")
io.send(@method).should == 101
io.send(@method).should == 120
io.send(@method).should == 97
io.getbyte.should == 101
io.getbyte.should == 120
io.getbyte.should == 97
end
end

View file

@ -8,9 +8,9 @@ describe "StringIO#getc" do
it "returns the character at the current position" do
io = StringIO.new("example")
io.send(@method).should == ?e
io.send(@method).should == ?x
io.send(@method).should == ?a
io.getc.should == ?e
io.getc.should == ?x
io.getc.should == ?a
end
end

View file

@ -12,32 +12,32 @@ describe "StringIO#getch" do
it "returns the character at the current position" do
io = StringIO.new("example")
io.send(@method).should == ?e
io.send(@method).should == ?x
io.send(@method).should == ?a
io.getch.should == ?e
io.getch.should == ?x
io.getch.should == ?a
end
with_feature :encoding do
it "increments #pos by the byte size of the character in multibyte strings" do
io = StringIO.new("föóbar")
io.send(@method); io.pos.should == 1 # "f" has byte size 1
io.send(@method); io.pos.should == 3 # "ö" has byte size 2
io.send(@method); io.pos.should == 5 # "ó" has byte size 2
io.send(@method); io.pos.should == 6 # "b" has byte size 1
io.getch; io.pos.should == 1 # "f" has byte size 1
io.getch; io.pos.should == 3 # "ö" has byte size 2
io.getch; io.pos.should == 5 # "ó" has byte size 2
io.getch; io.pos.should == 6 # "b" has byte size 1
end
end
it "returns nil at the end of the string" do
# empty string case
io = StringIO.new("")
io.send(@method).should == nil
io.send(@method).should == nil
io.getch.should == nil
io.getch.should == nil
# non-empty string case
io = StringIO.new("a")
io.send(@method) # skip one
io.send(@method).should == nil
io.getch # skip one
io.getch.should == nil
end
describe "StringIO#getch when self is not readable" do

View file

@ -8,10 +8,10 @@ describe "StringIO#readbyte" do
it "reads the next 8-bit byte from self's current position" do
io = StringIO.new("example")
io.send(@method).should == 101
io.readbyte.should == 101
io.pos = 4
io.send(@method).should == 112
io.readbyte.should == 112
end
end

View file

@ -8,10 +8,10 @@ describe "StringIO#readchar" do
it "reads the next 8-bit byte from self's current position" do
io = StringIO.new("example")
io.send(@method).should == ?e
io.readchar.should == ?e
io.pos = 4
io.send(@method).should == ?p
io.readchar.should == ?p
end
end

View file

@ -24,6 +24,8 @@ describe "Zlib.crc32" do
Zlib.crc32(test_string, 1).should == 1809313411
Zlib.crc32(test_string, 2**8).should == 1722745982
Zlib.crc32(test_string, 2**16).should == 1932511220
Zlib.crc32("p", ~305419896).should == 4046865307
Zlib.crc32("p", -305419897).should == 4046865307
lambda { Zlib.crc32(test_string, 2**128) }.should raise_error(RangeError)
end

View file

@ -139,21 +139,21 @@ describe "C-API Encoding function" do
it_behaves_like :rb_enc_get_index, :rb_enc_get_index
it "returns the index of the encoding of a Symbol" do
@s.send(@method, :symbol).should >= 0
@s.rb_enc_get_index(:symbol).should >= 0
end
it "returns -1 as the index of nil" do
@s.send(@method, nil).should == -1
@s.rb_enc_get_index(nil).should == -1
end
it "returns -1 as the index for immediates" do
@s.send(@method, 1).should == -1
@s.rb_enc_get_index(1).should == -1
end
ruby_version_is "2.6" do
it "returns -1 for an object without an encoding" do
obj = Object.new
@s.send(@method, obj).should == -1
@s.rb_enc_get_index(obj).should == -1
end
end
end

View file

@ -813,6 +813,15 @@ describe "CApiObject" do
it "returns nil if the instance variable has not been initialized" do
@o.rb_ivar_get(@test, :@bar).should == nil
end
it "returns nil if the instance variable has not been initialized and is not a valid Ruby name" do
@o.rb_ivar_get(@test, :bar).should == nil
end
it 'returns the instance variable when it is not a valid Ruby name' do
@o.rb_ivar_set(@test, :foo, 27)
@o.rb_ivar_get(@test, :foo).should == 27
end
end
describe "rb_ivar_set" do
@ -820,6 +829,15 @@ describe "CApiObject" do
@o.rb_ivar_set(@test, :@foo, 42).should == 42
@test.instance_eval { @foo }.should == 42
end
it "sets and returns the instance variable on an object" do
@o.rb_ivar_set(@test, :@foo, 42).should == 42
@test.instance_eval { @foo }.should == 42
end
it 'sets and returns the instance variable when it is not a valid Ruby name' do
@o.rb_ivar_set(@test, :foo, 27).should == 27
end
end
describe "rb_ivar_defined" do
@ -830,6 +848,10 @@ describe "CApiObject" do
it "returns false if the instance variable is not defined" do
@o.rb_ivar_defined(@test, :@bar).should == false
end
it "does not throw an error if the instance variable is not a valid Ruby name" do
@o.rb_ivar_defined(@test, :bar).should == false
end
end
end
end

View file

@ -0,0 +1,21 @@
require_relative '../spec_helper'
describe "Array#pack" do
it "resists CVE-2018-16396 by tainting output based on input" do
"aAZBbHhuMmPp".each_char do |f|
["123456".taint].pack(f).tainted?.should be_true
end
end
end
describe "String#unpack" do
it "resists CVE-2018-16396 by tainting output based on input" do
"aAZBbHhuMm".each_char do |f|
"123456".taint.unpack(f).first.tainted?.should be_true
end
end
end

View file

@ -29,6 +29,13 @@ describe :basicobject_send, shared: true do
SendSpecs::Foo.send(@method, :bar).should == 'done'
end
it "raises a TypeError if the method name is not a string or symbol" do
-> { SendSpecs.send(@method, nil) }.should raise_error(TypeError, /not a symbol nor a string/)
-> { SendSpecs.send(@method, 42) }.should raise_error(TypeError, /not a symbol nor a string/)
-> { SendSpecs.send(@method, 3.14) }.should raise_error(TypeError, /not a symbol nor a string/)
-> { SendSpecs.send(@method, true) }.should raise_error(TypeError, /not a symbol nor a string/)
end
it "raises a NameError if the corresponding method can't be found" do
class SendSpecs::Foo
def bar

View file

@ -41,7 +41,7 @@ describe :kernel_raise, shared: true do
lambda { @object.raise(nil) }.should raise_error(TypeError)
end
it "re-raises the rescued exception" do
it "re-raises the previously rescued exception if no exception is specified" do
lambda do
begin
raise Exception, "outer"
@ -60,6 +60,22 @@ describe :kernel_raise, shared: true do
ScratchPad.recorded.should be_nil
end
it "re-raises a previously rescued exception without overwriting the backtrace" do
begin
raise 'raised'
rescue => raised
begin
raise_again_line = __LINE__; raise raised
rescue => raised_again
# This spec is written using #backtrace and matching the line number
# from the string, as backtrace_locations is a more advanced
# method that is not always supported by implementations.
raised_again.backtrace.first.should_not include(":#{raise_again_line}:")
end
end
end
it "allows Exception, message, and backtrace parameters" do
lambda do
@object.raise(ArgumentError, "message", caller)