mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to ruby/spec@8b743a3
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65388 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ecc707e233
commit
3e6337b88b
69 changed files with 742 additions and 141 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 == ""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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],
|
||||
|
|
33
spec/ruby/core/array/pack/shared/taint.rb
Normal file
33
spec/ruby/core/array/pack/shared/taint.rb
Normal 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
|
|
@ -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 == ""
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
52
spec/ruby/core/io/pread_spec.rb
Normal file
52
spec/ruby/core/io/pread_spec.rb
Normal 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
|
45
spec/ruby/core/io/pwrite_spec.rb
Normal file
45
spec/ruby/core/io/pwrite_spec.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
9
spec/ruby/core/proc/fixtures/proc_aref.rb
Normal file
9
spec/ruby/core/proc/fixtures/proc_aref.rb
Normal 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
|
10
spec/ruby/core/proc/fixtures/proc_aref_frozen.rb
Normal file
10
spec/ruby/core/proc/fixtures/proc_aref_frozen.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
17
spec/ruby/core/random/shared/bytes.rb
Normal file
17
spec/ruby/core/random/shared/bytes.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
11
spec/ruby/core/string/each_grapheme_cluster_spec.rb
Normal file
11
spec/ruby/core/string/each_grapheme_cluster_spec.rb
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
15
spec/ruby/core/string/grapheme_clusters_spec.rb
Normal file
15
spec/ruby/core/string/grapheme_clusters_spec.rb
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 == "%"
|
||||
|
|
16
spec/ruby/core/string/shared/grapheme_clusters.rb
Normal file
16
spec/ruby/core/string/shared/grapheme_clusters.rb
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]],
|
||||
|
|
|
@ -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"]],
|
||||
|
|
|
@ -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"]],
|
||||
|
|
|
@ -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 == [""]
|
||||
|
|
|
@ -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
|
||||
|
|
81
spec/ruby/core/string/unpack/shared/taint.rb
Normal file
81
spec/ruby/core/string/unpack/shared/taint.rb
Normal 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
|
|
@ -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 == [""]
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
9
spec/ruby/library/datetime/add_spec.rb
Normal file
9
spec/ruby/library/datetime/add_spec.rb
Normal 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
|
9
spec/ruby/library/datetime/subtract_spec.rb
Normal file
9
spec/ruby/library/datetime/subtract_spec.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
21
spec/ruby/security/cve_2018_16396_spec.rb
Normal file
21
spec/ruby/security/cve_2018_16396_spec.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue