mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to ruby/spec@4bc7a2b
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63652 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
78890babe7
commit
67078e81f5
24 changed files with 1220 additions and 313 deletions
|
@ -3,16 +3,20 @@ version: "{build}"
|
||||||
clone_depth: 5
|
clone_depth: 5
|
||||||
init:
|
init:
|
||||||
# To avoid duplicated executables in PATH, see https://github.com/ruby/spec/pull/468
|
# To avoid duplicated executables in PATH, see https://github.com/ruby/spec/pull/468
|
||||||
- set PATH=C:\ruby%RUBY_VERSION%\bin;C:\Program Files\7-Zip;C:\Program Files\AppVeyor\BuildAgent;C:\Program Files\Git\cmd;C:\Windows\system32;C:\Program Files;C:\Windows
|
- set PATH=C:\Ruby%ruby_version%\bin;C:\Program Files\7-Zip;C:\Program Files\AppVeyor\BuildAgent;C:\Program Files\Git\cmd;C:\Windows\system32;C:\Program Files;C:\Windows
|
||||||
# Loads trunk build and updates MSYS2 / MinGW to most recent gcc compiler
|
# Loads trunk build and updates MSYS2 / MinGW to most recent gcc compiler
|
||||||
- if %ruby_version%==_trunk (
|
- ps: |
|
||||||
appveyor DownloadFile https://ci.appveyor.com/api/projects/MSP-Greg/ruby-loco/artifacts/ruby_trunk.7z -FileName C:\ruby_trunk.7z &
|
if ($env:ruby_version -eq '_trunk') {
|
||||||
7z x C:\ruby_trunk.7z -oC:\ruby_trunk & C:\ruby_trunk\trunk_msys2.cmd)
|
$trunk_uri = 'https://ci.appveyor.com/api/projects/MSP-Greg/ruby-loco/artifacts/ruby_trunk.7z'
|
||||||
|
(New-Object Net.WebClient).DownloadFile($trunk_uri, 'C:\ruby_trunk.7z')
|
||||||
|
7z.exe x C:\ruby_trunk.7z -oC:\Ruby_trunk
|
||||||
|
}
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- RUBY_VERSION: 23-x64
|
- ruby_version: 24-x64
|
||||||
- RUBY_VERSION: 24-x64
|
- ruby_version: 25-x64
|
||||||
- RUBY_VERSION: _trunk # So the folder name is ruby_trunk
|
- ruby_version: _trunk # So the folder name is ruby_trunk
|
||||||
install:
|
install:
|
||||||
- git clone https://github.com/ruby/mspec.git ../mspec
|
- git clone https://github.com/ruby/mspec.git ../mspec
|
||||||
build: off
|
build: off
|
||||||
|
|
|
@ -2,12 +2,11 @@ require_relative '../../spec_helper'
|
||||||
require_relative 'fixtures/classes'
|
require_relative 'fixtures/classes'
|
||||||
|
|
||||||
describe "Enumerable#all?" do
|
describe "Enumerable#all?" do
|
||||||
|
|
||||||
before :each do
|
before :each do
|
||||||
@enum = EnumerableSpecs::Numerous.new
|
@enum = EnumerableSpecs::Numerous.new
|
||||||
@empty = EnumerableSpecs::Empty.new()
|
@empty = EnumerableSpecs::Empty.new()
|
||||||
@enum1 = [0, 1, 2, -1]
|
@enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1)
|
||||||
@enum2 = [nil, false, true]
|
@enum2 = EnumerableSpecs::Numerous.new(nil, false, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "always returns true on empty enumeration" do
|
it "always returns true on empty enumeration" do
|
||||||
|
@ -21,6 +20,21 @@ describe "Enumerable#all?" do
|
||||||
{}.all? { nil }.should == true
|
{}.all? { nil }.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "raises an ArgumentError when more than 1 argument is provided" do
|
||||||
|
lambda { @enum.all?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
|
lambda { [].all?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
|
lambda { {}.all?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is ""..."2.5" do
|
||||||
|
it "raises an ArgumentError when any arguments provided" do
|
||||||
|
lambda { @enum.all?(Proc.new {}) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @enum.all?(nil) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @empty.all?(1) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @enum1.all?(1) {} }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "does not hide exceptions out of #each" do
|
it "does not hide exceptions out of #each" do
|
||||||
lambda {
|
lambda {
|
||||||
EnumerableSpecs::ThrowingEach.new.all?
|
EnumerableSpecs::ThrowingEach.new.all?
|
||||||
|
@ -58,16 +72,6 @@ describe "Enumerable#all?" do
|
||||||
multi = EnumerableSpecs::YieldsMultiWithFalse.new
|
multi = EnumerableSpecs::YieldsMultiWithFalse.new
|
||||||
multi.all?.should be_true
|
multi.all?.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
ruby_version_is "2.5" do
|
|
||||||
describe "given a pattern argument" do
|
|
||||||
# This spec should be replaced by more extensive ones
|
|
||||||
it "returns true iff all match that pattern" do
|
|
||||||
@enum.all?(Integer).should == true
|
|
||||||
@enum2.all?(NilClass).should == false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with block" do
|
describe "with block" do
|
||||||
|
@ -117,14 +121,79 @@ describe "Enumerable#all?" do
|
||||||
|
|
||||||
it "gathers initial args as elements when each yields multiple" do
|
it "gathers initial args as elements when each yields multiple" do
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
multi.all? {|e| !(Array === e) }.should be_true
|
yielded = []
|
||||||
|
multi.all? { |e| yielded << e }.should == true
|
||||||
|
yielded.should == [1, 3, 6]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "yields multiple arguments when each yields multiple" do
|
it "yields multiple arguments when each yields multiple" do
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
yielded = []
|
yielded = []
|
||||||
multi.all? {|e, i| yielded << [e, i] }
|
multi.all? { |*args| yielded << args }.should == true
|
||||||
yielded.should == [[1, 2], [3, 4], [6, 7]]
|
yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.5" do
|
||||||
|
describe 'when given a pattern argument' do
|
||||||
|
it "calls `===` on the pattern the return value " do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 }
|
||||||
|
@enum1.all?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ignores block" do
|
||||||
|
@enum2.all?(NilClass) { raise }.should == false
|
||||||
|
[1, 2, nil].all?(NilClass) { raise }.should == false
|
||||||
|
{a: 1}.all?(Array) { raise }.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "always returns true on empty enumeration" do
|
||||||
|
@empty.all?(Integer).should == true
|
||||||
|
[].all?(Integer).should == true
|
||||||
|
{}.all?(NilClass).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of #each" do
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.all?(Integer)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if the pattern never returns false or nil" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| 42 }
|
||||||
|
@enum.all?(pattern).should == true
|
||||||
|
|
||||||
|
[1, 42, 3].all?(pattern).should == true
|
||||||
|
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| Array === x }
|
||||||
|
{a: 1, b: 2}.all?(pattern).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if the pattern ever returns false or nil" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 }
|
||||||
|
@enum1.all?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
|
||||||
|
[1, 2, 3, -1].all?(pattern).should == false
|
||||||
|
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x[1] >= 0 }
|
||||||
|
{a: 1, b: -1}.all?(pattern).should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of pattern#===" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
|
||||||
|
lambda {
|
||||||
|
@enum.all?(pattern)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls the pattern with gathered array when yielded with multiple arguments" do
|
||||||
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { true }
|
||||||
|
multi.all?(pattern).should == true
|
||||||
|
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,9 +4,9 @@ require_relative 'fixtures/classes'
|
||||||
describe "Enumerable#any?" do
|
describe "Enumerable#any?" do
|
||||||
before :each do
|
before :each do
|
||||||
@enum = EnumerableSpecs::Numerous.new
|
@enum = EnumerableSpecs::Numerous.new
|
||||||
@empty = EnumerableSpecs::Empty.new()
|
@empty = EnumerableSpecs::Empty.new
|
||||||
@enum1 = [0, 1, 2, -1]
|
@enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1)
|
||||||
@enum2 = [nil, false, true]
|
@enum2 = EnumerableSpecs::Numerous.new(nil, false, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "always returns false on empty enumeration" do
|
it "always returns false on empty enumeration" do
|
||||||
|
@ -86,7 +86,7 @@ describe "Enumerable#any?" do
|
||||||
@enum2.any? { |i| i == nil }.should == true
|
@enum2.any? { |i| i == nil }.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "any? should return false if the block never returns other than false or nil" do
|
it "returns false if the block never returns other than false or nil" do
|
||||||
@enum.any? { false }.should == false
|
@enum.any? { false }.should == false
|
||||||
@enum.any? { nil }.should == false
|
@enum.any? { nil }.should == false
|
||||||
|
|
||||||
|
@ -134,32 +134,21 @@ describe "Enumerable#any?" do
|
||||||
|
|
||||||
it "gathers initial args as elements when each yields multiple" do
|
it "gathers initial args as elements when each yields multiple" do
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
multi.any? {|e| e == 1 }.should be_true
|
yielded = []
|
||||||
|
multi.any? { |e| yielded << e; false }.should == false
|
||||||
|
yielded.should == [1, 3, 6]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "yields multiple arguments when each yields multiple" do
|
it "yields multiple arguments when each yields multiple" do
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
yielded = []
|
yielded = []
|
||||||
multi.any? {|e, i| yielded << [e, i] }
|
multi.any? { |*args| yielded << args; false }.should == false
|
||||||
yielded.should == [[1, 2]]
|
yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ruby_version_is "2.5" do
|
ruby_version_is "2.5" do
|
||||||
describe 'when given a pattern argument' do
|
describe 'when given a pattern argument' do
|
||||||
class EnumerableSpecs::Pattern
|
|
||||||
attr_reader :yielded
|
|
||||||
def initialize(&block)
|
|
||||||
@block = block
|
|
||||||
@yielded = []
|
|
||||||
end
|
|
||||||
def ===(*args)
|
|
||||||
@yielded << args
|
|
||||||
@block.call(*args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it "calls `===` on the pattern the return value " do
|
it "calls `===` on the pattern the return value " do
|
||||||
pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
|
pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
|
||||||
@enum1.any?(pattern).should == true
|
@enum1.any?(pattern).should == true
|
||||||
|
@ -195,7 +184,7 @@ describe "Enumerable#any?" do
|
||||||
{a: 1, b: 2}.any?(pattern).should == true
|
{a: 1, b: 2}.any?(pattern).should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "any? should return false if the block never returns other than false or nil" do
|
it "returns false if the block never returns other than false or nil" do
|
||||||
pattern = EnumerableSpecs::Pattern.new { |x| nil }
|
pattern = EnumerableSpecs::Pattern.new { |x| nil }
|
||||||
@enum1.any?(pattern).should == false
|
@enum1.any?(pattern).should == false
|
||||||
pattern.yielded.should == [[0], [1], [2], [-1]]
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
@ -204,7 +193,7 @@ describe "Enumerable#any?" do
|
||||||
{a: 1}.any?(pattern).should == false
|
{a: 1}.any?(pattern).should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not hide exceptions out of the block" do
|
it "does not hide exceptions out of pattern#===" do
|
||||||
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
|
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
|
||||||
lambda {
|
lambda {
|
||||||
@enum.any?(pattern)
|
@enum.any?(pattern)
|
||||||
|
@ -212,13 +201,10 @@ describe "Enumerable#any?" do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "calls the pattern with gathered array when yielded with multiple arguments" do
|
it "calls the pattern with gathered array when yielded with multiple arguments" do
|
||||||
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
pattern = EnumerableSpecs::Pattern.new { false }
|
pattern = EnumerableSpecs::Pattern.new { false }
|
||||||
EnumerableSpecs::YieldsMixed2.new.any?(pattern).should == false
|
multi.any?(pattern).should == false
|
||||||
pattern.yielded.should == EnumerableSpecs::YieldsMixed2.gathered_yields.map { |x| [x] }
|
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
|
||||||
|
|
||||||
pattern = EnumerableSpecs::Pattern.new { false }
|
|
||||||
{a: 1, b: 2}.any?(pattern).should == false
|
|
||||||
pattern.yielded.should == [[[:a, 1]], [[:b, 2]]]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -328,4 +328,18 @@ module EnumerableSpecs
|
||||||
EnumerableMapping.new(self, block)
|
EnumerableMapping.new(self, block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Pattern
|
||||||
|
attr_reader :yielded
|
||||||
|
|
||||||
|
def initialize(&block)
|
||||||
|
@block = block
|
||||||
|
@yielded = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def ===(*args)
|
||||||
|
@yielded << args
|
||||||
|
@block.call(*args)
|
||||||
|
end
|
||||||
|
end
|
||||||
end # EnumerableSpecs utility classes
|
end # EnumerableSpecs utility classes
|
||||||
|
|
|
@ -2,67 +2,164 @@ require_relative '../../spec_helper'
|
||||||
require_relative 'fixtures/classes'
|
require_relative 'fixtures/classes'
|
||||||
|
|
||||||
describe "Enumerable#none?" do
|
describe "Enumerable#none?" do
|
||||||
it "returns true if none of the elements in self are true" do
|
before :each do
|
||||||
e = EnumerableSpecs::Numerous.new(false, nil, false)
|
@empty = EnumerableSpecs::Empty.new
|
||||||
e.none?.should be_true
|
@enum = EnumerableSpecs::Numerous.new
|
||||||
|
@enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1)
|
||||||
|
@enum2 = EnumerableSpecs::Numerous.new(nil, false, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false if at least one of the elements in self are true" do
|
it "always returns true on empty enumeration" do
|
||||||
e = EnumerableSpecs::Numerous.new(false, nil, true, false)
|
@empty.none?.should == true
|
||||||
e.none?.should be_false
|
@empty.none? { true }.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "gathers whole arrays as elements when each yields multiple" do
|
it "raises an ArgumentError when more than 1 argument is provided" do
|
||||||
# This spec doesn't spec what it says it does
|
lambda { @enum.none?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
multi = EnumerableSpecs::YieldsMultiWithFalse.new
|
lambda { [].none?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
multi.none?.should be_false
|
lambda { {}.none?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is ""..."2.5" do
|
||||||
|
it "raises an ArgumentError when any arguments provided" do
|
||||||
|
lambda { @enum.none?(Proc.new {}) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @enum.none?(nil) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @empty.none?(1) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @enum.none?(1) {} }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of #each" do
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.none?
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.none? { false }
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with no block" do
|
||||||
|
it "returns true if none of the elements in self are true" do
|
||||||
|
e = EnumerableSpecs::Numerous.new(false, nil, false)
|
||||||
|
e.none?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if at least one of the elements in self are true" do
|
||||||
|
e = EnumerableSpecs::Numerous.new(false, nil, true, false)
|
||||||
|
e.none?.should be_false
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with a block" do
|
||||||
|
before :each do
|
||||||
|
@e = EnumerableSpecs::Numerous.new(1,1,2,3,4)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes each element to the block in turn until it returns true" do
|
||||||
|
acc = []
|
||||||
|
@e.none? {|e| acc << e; false }
|
||||||
|
acc.should == [1,1,2,3,4]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "stops passing elements to the block when it returns true" do
|
||||||
|
acc = []
|
||||||
|
@e.none? {|e| acc << e; e == 3 ? true : false }
|
||||||
|
acc.should == [1,1,2,3]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if the block never returns true" do
|
||||||
|
@e.none? {|e| false }.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if the block ever returns true" do
|
||||||
|
@e.none? {|e| e == 3 ? true : false }.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of the block" do
|
||||||
|
lambda {
|
||||||
|
@enum.none? { raise "from block" }
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "gathers initial args as elements when each yields multiple" do
|
||||||
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
|
yielded = []
|
||||||
|
multi.none? { |e| yielded << e; false }
|
||||||
|
yielded.should == [1, 3, 6]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "yields multiple arguments when each yields multiple" do
|
||||||
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
|
yielded = []
|
||||||
|
multi.none? { |*args| yielded << args; false }
|
||||||
|
yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ruby_version_is "2.5" do
|
ruby_version_is "2.5" do
|
||||||
describe "given a pattern argument" do
|
describe 'when given a pattern argument' do
|
||||||
# This spec should be replaced by more extensive ones
|
it "calls `===` on the pattern the return value " do
|
||||||
it "returns true iff none match that pattern" do
|
pattern = EnumerableSpecs::Pattern.new { |x| x == 3 }
|
||||||
EnumerableSpecs::Numerous.new.none?(Float).should == true
|
@enum1.none?(pattern).should == true
|
||||||
[nil, false, true].none?(NilClass).should == false
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ignores block" do
|
||||||
|
@enum2.none?(Integer) { raise }.should == true
|
||||||
|
[1, 2, nil].none?(TrueClass) { raise }.should == true
|
||||||
|
{a: 1}.none?(Hash) { raise }.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "always returns true on empty enumeration" do
|
||||||
|
@empty.none?(Integer).should == true
|
||||||
|
[].none?(Integer).should == true
|
||||||
|
{}.none?(NilClass).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of #each" do
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.none?(Integer)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if the pattern never returns a truthy value" do
|
||||||
|
@enum2.none?(Integer).should == true
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| nil }
|
||||||
|
@enum.none?(pattern).should == true
|
||||||
|
|
||||||
|
[1, 42, 3].none?(pattern).should == true
|
||||||
|
{a: 1, b: 2}.none?(pattern).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if the pattern ever returns other than false or nil" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x < 0 }
|
||||||
|
@enum1.none?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
|
||||||
|
[1, 2, 3, -1].none?(pattern).should == false
|
||||||
|
{a: 1}.none?(Array).should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of pattern#===" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
|
||||||
|
lambda {
|
||||||
|
@enum.none?(pattern)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls the pattern with gathered array when yielded with multiple arguments" do
|
||||||
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { false }
|
||||||
|
multi.none?(pattern).should == true
|
||||||
|
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Enumerable#none? with a block" do
|
|
||||||
before :each do
|
|
||||||
@e = EnumerableSpecs::Numerous.new(1,1,2,3,4)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "passes each element to the block in turn until it returns true" do
|
|
||||||
acc = []
|
|
||||||
@e.none? {|e| acc << e; false }
|
|
||||||
acc.should == [1,1,2,3,4]
|
|
||||||
end
|
|
||||||
|
|
||||||
it "stops passing elements to the block when it returns true" do
|
|
||||||
acc = []
|
|
||||||
@e.none? {|e| acc << e; e == 3 ? true : false }
|
|
||||||
acc.should == [1,1,2,3]
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns true if the block never returns true" do
|
|
||||||
@e.none? {|e| false }.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns false if the block ever returns true" do
|
|
||||||
@e.none? {|e| e == 3 ? true : false }.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "gathers initial args as elements when each yields multiple" do
|
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
|
||||||
multi.none? {|e| e == [1, 2] }.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it "yields multiple arguments when each yields multiple" do
|
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
|
||||||
yielded = []
|
|
||||||
multi.none? {|e, i| yielded << [e, i] }
|
|
||||||
yielded.should == [[1, 2]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -2,44 +2,44 @@ require_relative '../../spec_helper'
|
||||||
require_relative 'fixtures/classes'
|
require_relative 'fixtures/classes'
|
||||||
|
|
||||||
describe "Enumerable#one?" do
|
describe "Enumerable#one?" do
|
||||||
describe "when passed a block" do
|
before :each do
|
||||||
it "returns true if block returns true once" do
|
@empty = EnumerableSpecs::Empty.new
|
||||||
[:a, :b, :c].one? { |s| s == :a }.should be_true
|
@enum = EnumerableSpecs::Numerous.new
|
||||||
end
|
@enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1)
|
||||||
|
@enum2 = EnumerableSpecs::Numerous.new(nil, false, true)
|
||||||
|
end
|
||||||
|
|
||||||
it "returns false if the block returns true more than once" do
|
it "always returns false on empty enumeration" do
|
||||||
[:a, :b, :c].one? { |s| s == :a || s == :b }.should be_false
|
@empty.one?.should == false
|
||||||
end
|
@empty.one? { true }.should == false
|
||||||
|
end
|
||||||
|
|
||||||
it "returns false if the block only returns false" do
|
it "raises an ArgumentError when more than 1 argument is provided" do
|
||||||
[:a, :b, :c].one? { |s| s == :d }.should be_false
|
lambda { @enum.one?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
end
|
lambda { [].one?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
|
lambda { {}.one?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
it "gathers initial args as elements when each yields multiple" do
|
ruby_version_is ""..."2.5" do
|
||||||
# This spec doesn't spec what it says it does
|
it "raises an ArgumentError when any arguments provided" do
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
lambda { @enum.one?(Proc.new {}) }.should raise_error(ArgumentError)
|
||||||
multi.one? {|e| e == 1 }.should be_true
|
lambda { @enum.one?(nil) }.should raise_error(ArgumentError)
|
||||||
end
|
lambda { @empty.one?(1) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @enum.one?(1) {} }.should raise_error(ArgumentError)
|
||||||
it "yields multiple arguments when each yields multiple" do
|
|
||||||
multi = EnumerableSpecs::YieldsMulti.new
|
|
||||||
yielded = []
|
|
||||||
multi.one? {|e, i| yielded << [e, i] }
|
|
||||||
yielded.should == [[1, 2], [3, 4]]
|
|
||||||
end
|
|
||||||
|
|
||||||
ruby_version_is "2.5" do
|
|
||||||
describe "given a pattern argument" do
|
|
||||||
# This spec should be replaced by more extensive ones
|
|
||||||
it "returns true iff none match that pattern" do
|
|
||||||
EnumerableSpecs::Numerous.new.one?(Integer).should == false
|
|
||||||
[nil, false, true].one?(NilClass).should == true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when not passed a block" do
|
it "does not hide exceptions out of #each" do
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.one?
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.one? { false }
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with no block" do
|
||||||
it "returns true if only one element evaluates to true" do
|
it "returns true if only one element evaluates to true" do
|
||||||
[false, nil, true].one?.should be_true
|
[false, nil, true].one?.should be_true
|
||||||
end
|
end
|
||||||
|
@ -57,4 +57,111 @@ describe "Enumerable#one?" do
|
||||||
multi.one?.should be_false
|
multi.one?.should be_false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "with a block" do
|
||||||
|
it "returns true if block returns true once" do
|
||||||
|
[:a, :b, :c].one? { |s| s == :a }.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if the block returns true more than once" do
|
||||||
|
[:a, :b, :c].one? { |s| s == :a || s == :b }.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if the block only returns false" do
|
||||||
|
[:a, :b, :c].one? { |s| s == :d }.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of the block" do
|
||||||
|
lambda {
|
||||||
|
@enum.one? { raise "from block" }
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
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
|
||||||
|
yielded.should == [1, 3, 6]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "yields multiple arguments when each yields multiple" do
|
||||||
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
|
yielded = []
|
||||||
|
multi.one? { |*args| yielded << args; false }.should == false
|
||||||
|
yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
ruby_version_is "2.5" do
|
||||||
|
describe 'when given a pattern argument' do
|
||||||
|
it "calls `===` on the pattern the return value " do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x == 1 }
|
||||||
|
@enum1.one?(pattern).should == true
|
||||||
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ignores block" do
|
||||||
|
@enum2.one?(NilClass) { raise }.should == true
|
||||||
|
[1, 2, nil].one?(NilClass) { raise }.should == true
|
||||||
|
{a: 1}.one?(Array) { raise }.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "always returns false on empty enumeration" do
|
||||||
|
@empty.one?(Integer).should == false
|
||||||
|
[].one?(Integer).should == false
|
||||||
|
{}.one?(NilClass).should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of #each" do
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.one?(Integer)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if the pattern returns a truthy value only once" do
|
||||||
|
@enum2.one?(NilClass).should == true
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
|
||||||
|
@enum1.one?(pattern).should == true
|
||||||
|
|
||||||
|
[1, 2, 42, 3].one?(pattern).should == true
|
||||||
|
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] }
|
||||||
|
{a: 1, b: 2}.one?(pattern).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if the pattern returns a truthy value more than once" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| !x }
|
||||||
|
@enum2.one?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[nil], [false]]
|
||||||
|
|
||||||
|
[1, 2, 3].one?(Integer).should == false
|
||||||
|
{a: 1, b: 2}.one?(Array).should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if the pattern never returns a truthy value" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| nil }
|
||||||
|
@enum1.one?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
|
||||||
|
[1, 2, 3].one?(pattern).should == false
|
||||||
|
{a: 1}.one?(pattern).should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of pattern#===" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
|
||||||
|
lambda {
|
||||||
|
@enum.one?(pattern)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls the pattern with gathered array when yielded with multiple arguments" do
|
||||||
|
multi = EnumerableSpecs::YieldsMulti.new
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { false }
|
||||||
|
multi.one?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,6 +60,25 @@ describe "Kernel#autoload" do
|
||||||
ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "#{frozen_error_class} - nil"
|
ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "#{frozen_error_class} - nil"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "when called from included module's method" do
|
||||||
|
before :all do
|
||||||
|
@path = fixture(__FILE__, "autoload_from_included_module.rb")
|
||||||
|
KernelSpecs::AutoloadMethodIncluder.new.setup_autoload(@path)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "setups the autoload on the included module" do
|
||||||
|
KernelSpecs::AutoloadMethod.autoload?(:AutoloadFromIncludedModule).should == @path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "the autoload is reacheable from the class too" do
|
||||||
|
KernelSpecs::AutoloadMethodIncluder.autoload?(:AutoloadFromIncludedModule).should == @path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "the autoload relative to the included module works" do
|
||||||
|
KernelSpecs::AutoloadMethod::AutoloadFromIncludedModule.loaded.should == :autoload_from_included_module
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Kernel#autoload?" do
|
describe "Kernel#autoload?" do
|
||||||
|
@ -107,6 +126,25 @@ describe "Kernel.autoload" do
|
||||||
p.should_receive(:to_path).and_return @non_existent
|
p.should_receive(:to_path).and_return @non_existent
|
||||||
Kernel.autoload :KSAutoloadAA, p
|
Kernel.autoload :KSAutoloadAA, p
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "when called from included module's method" do
|
||||||
|
before :all do
|
||||||
|
@path = fixture(__FILE__, "autoload_from_included_module2.rb")
|
||||||
|
KernelSpecs::AutoloadMethodIncluder2.new.setup_autoload(@path)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "setups the autoload on the included module" do
|
||||||
|
KernelSpecs::AutoloadMethod2.autoload?(:AutoloadFromIncludedModule2).should == @path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "the autoload is reacheable from the class too" do
|
||||||
|
KernelSpecs::AutoloadMethodIncluder2.autoload?(:AutoloadFromIncludedModule2).should == @path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "the autoload relative to the included module works" do
|
||||||
|
KernelSpecs::AutoloadMethod2::AutoloadFromIncludedModule2.loaded.should == :autoload_from_included_module2
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Kernel.autoload?" do
|
describe "Kernel.autoload?" do
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
module KernelSpecs
|
||||||
|
module AutoloadMethod
|
||||||
|
module AutoloadFromIncludedModule
|
||||||
|
def self.loaded
|
||||||
|
:autoload_from_included_module
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
module KernelSpecs
|
||||||
|
module AutoloadMethod2
|
||||||
|
module AutoloadFromIncludedModule2
|
||||||
|
def self.loaded
|
||||||
|
:autoload_from_included_module2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -378,6 +378,49 @@ module KernelSpecs
|
||||||
[3, 4]
|
[3, 4]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module AutoloadMethod
|
||||||
|
def setup_autoload(file)
|
||||||
|
autoload :AutoloadFromIncludedModule, file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class AutoloadMethodIncluder
|
||||||
|
include AutoloadMethod
|
||||||
|
end
|
||||||
|
|
||||||
|
module AutoloadMethod2
|
||||||
|
def setup_autoload(file)
|
||||||
|
Kernel.autoload :AutoloadFromIncludedModule2, file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class AutoloadMethodIncluder2
|
||||||
|
include AutoloadMethod2
|
||||||
|
end
|
||||||
|
|
||||||
|
class WarnInNestedCall
|
||||||
|
def f4(s = "", n)
|
||||||
|
f3(s, n)
|
||||||
|
end
|
||||||
|
|
||||||
|
def f3(s, n)
|
||||||
|
f2(s, n)
|
||||||
|
end
|
||||||
|
|
||||||
|
def f2(s, n)
|
||||||
|
f1(s, n)
|
||||||
|
end
|
||||||
|
|
||||||
|
def f1(s, n)
|
||||||
|
warn(s, uplevel: n)
|
||||||
|
end
|
||||||
|
|
||||||
|
def warn_call_lineno; method(:f1).source_location[1] + 1; end
|
||||||
|
def f1_call_lineno; method(:f2).source_location[1] + 1; end
|
||||||
|
def f2_call_lineno; method(:f3).source_location[1] + 1; end
|
||||||
|
def f3_call_lineno; method(:f4).source_location[1] + 1; end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class EvalSpecs
|
class EvalSpecs
|
||||||
|
|
20
spec/ruby/core/kernel/shared/then.rb
Normal file
20
spec/ruby/core/kernel/shared/then.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
describe :kernel_then, shared: true do
|
||||||
|
it "yields self" do
|
||||||
|
object = Object.new
|
||||||
|
object.send(@method) { |o| o.should equal object }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the block return value" do
|
||||||
|
object = Object.new
|
||||||
|
object.send(@method) { 42 }.should equal 42
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a sized Enumerator when no block given" do
|
||||||
|
object = Object.new
|
||||||
|
enum = object.send(@method)
|
||||||
|
enum.should be_an_instance_of Enumerator
|
||||||
|
enum.size.should equal 1
|
||||||
|
enum.peek.should equal object
|
||||||
|
enum.first.should equal object
|
||||||
|
end
|
||||||
|
end
|
8
spec/ruby/core/kernel/then_spec.rb
Normal file
8
spec/ruby/core/kernel/then_spec.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
require_relative '../../spec_helper'
|
||||||
|
require_relative 'shared/then'
|
||||||
|
|
||||||
|
ruby_version_is "2.6" do
|
||||||
|
describe "Kernel#then" do
|
||||||
|
it_behaves_like :kernel_then, :then
|
||||||
|
end
|
||||||
|
end
|
|
@ -76,4 +76,60 @@ describe "Kernel#warn" do
|
||||||
warn("")
|
warn("")
|
||||||
}.should output(nil, /\n/)
|
}.should output(nil, /\n/)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.5" do
|
||||||
|
describe ":uplevel keyword argument" do
|
||||||
|
before :each do
|
||||||
|
$VERBOSE = true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "prepends a message with specified line from the backtrace" do
|
||||||
|
w = KernelSpecs::WarnInNestedCall.new
|
||||||
|
|
||||||
|
-> { w.f4("foo", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: foo|)
|
||||||
|
-> { w.f4("foo", 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: foo|)
|
||||||
|
-> { w.f4("foo", 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: foo|)
|
||||||
|
-> { w.f4("foo", 3) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f3_call_lineno}: warning: foo|)
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_bug "#14846", "2.5"..."2.6" do
|
||||||
|
it "does not prepend caller information if line number is too big" do
|
||||||
|
w = KernelSpecs::WarnInNestedCall.new
|
||||||
|
-> { w.f4("foo", 100) }.should output(nil, "warning: foo\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "prepends even if a message is empty or nil" do
|
||||||
|
w = KernelSpecs::WarnInNestedCall.new
|
||||||
|
|
||||||
|
-> { w.f4("", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|)
|
||||||
|
-> { w.f4(nil, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts value to Integer" do
|
||||||
|
w = KernelSpecs::WarnInNestedCall.new
|
||||||
|
|
||||||
|
-> { w.f4(0.1) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|)
|
||||||
|
-> { w.f4(Rational(1, 2)) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises ArgumentError if passed negative value" do
|
||||||
|
-> { warn "", uplevel: -2 }.should raise_error(ArgumentError)
|
||||||
|
-> { warn "", uplevel: -100 }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_bug "#14846", "2.5"..."2.6" do
|
||||||
|
it "raises ArgumentError if passed -1" do
|
||||||
|
-> { warn "", uplevel: -1 }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises TypeError if passed not Integer" do
|
||||||
|
-> { warn "", uplevel: "" }.should raise_error(TypeError)
|
||||||
|
-> { warn "", uplevel: [] }.should raise_error(TypeError)
|
||||||
|
-> { warn "", uplevel: {} }.should raise_error(TypeError)
|
||||||
|
-> { warn "", uplevel: Object.new }.should raise_error(TypeError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,29 +1,8 @@
|
||||||
require_relative '../../spec_helper'
|
require_relative '../../spec_helper'
|
||||||
|
require_relative 'shared/then'
|
||||||
|
|
||||||
ruby_version_is "2.5" do
|
ruby_version_is "2.5" do
|
||||||
describe "Kernel#yield_self" do
|
describe "Kernel#yield_self" do
|
||||||
it "yields self" do
|
it_behaves_like :kernel_then, :yield_self
|
||||||
object = Object.new
|
|
||||||
object.yield_self { |o| o.should equal object }
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns the block return value" do
|
|
||||||
object = Object.new
|
|
||||||
object.yield_self { 42 }.should equal 42
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns a sized Enumerator when no block given" do
|
|
||||||
object = Object.new
|
|
||||||
enum = object.yield_self
|
|
||||||
enum.should be_an_instance_of Enumerator
|
|
||||||
enum.size.should equal 1
|
|
||||||
enum.peek.should equal object
|
|
||||||
enum.first.should equal object
|
|
||||||
end
|
|
||||||
|
|
||||||
it "has an alias `then`" do
|
|
||||||
object = Object.new
|
|
||||||
object.then { 42 }.should equal 42
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,10 +13,18 @@ describe "String#dump" do
|
||||||
"foo\n".untrust.dump.untrusted?.should == true
|
"foo\n".untrust.dump.untrusted?.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does not take into account if a string is frozen" do
|
||||||
|
"foo".freeze.dump.frozen?.should == false
|
||||||
|
end
|
||||||
|
|
||||||
it "returns a subclass instance" do
|
it "returns a subclass instance" do
|
||||||
StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString)
|
StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "wraps string with \"" do
|
||||||
|
"foo".dump.should == '"foo"'
|
||||||
|
end
|
||||||
|
|
||||||
it "returns a string with special characters replaced with \\<char> notation" do
|
it "returns a string with special characters replaced with \\<char> notation" do
|
||||||
[ ["\a", '"\\a"'],
|
[ ["\a", '"\\a"'],
|
||||||
["\b", '"\\b"'],
|
["\b", '"\\b"'],
|
||||||
|
@ -35,10 +43,11 @@ describe "String#dump" do
|
||||||
].should be_computed_by(:dump)
|
].should be_computed_by(:dump)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns a string with \\#<char> when # is followed by $, @, {" do
|
it "returns a string with \\#<char> when # is followed by $, @, @@, {" do
|
||||||
[ ["\#$", '"\\#$"'],
|
[ ["\#$PATH", '"\\#$PATH"'],
|
||||||
["\#@", '"\\#@"'],
|
["\#@a", '"\\#@a"'],
|
||||||
["\#{", '"\\#{"']
|
["\#@@a", '"\\#@@a"'],
|
||||||
|
["\#{a}", '"\\#{a}"']
|
||||||
].should be_computed_by(:dump)
|
].should be_computed_by(:dump)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -381,7 +390,7 @@ describe "String#dump" do
|
||||||
end
|
end
|
||||||
|
|
||||||
ruby_version_is '2.4' do
|
ruby_version_is '2.4' do
|
||||||
it "returns a string with multi-byte UTF-8 characters replaced by \\u{} notation with lower-case hex digits" do
|
it "returns a string with multi-byte UTF-8 characters replaced by \\u{} notation with upper-case hex digits" do
|
||||||
[ [0200.chr('utf-8'), '"\u0080"'],
|
[ [0200.chr('utf-8'), '"\u0080"'],
|
||||||
[0201.chr('utf-8'), '"\u0081"'],
|
[0201.chr('utf-8'), '"\u0081"'],
|
||||||
[0202.chr('utf-8'), '"\u0082"'],
|
[0202.chr('utf-8'), '"\u0082"'],
|
||||||
|
@ -421,4 +430,10 @@ describe "String#dump" do
|
||||||
"\u{876}".encode('utf-16be').dump.end_with?(".force_encoding(\"UTF-16BE\")").should be_true
|
"\u{876}".encode('utf-16be').dump.end_with?(".force_encoding(\"UTF-16BE\")").should be_true
|
||||||
"\u{876}".encode('utf-16le').dump.end_with?(".force_encoding(\"UTF-16LE\")").should be_true
|
"\u{876}".encode('utf-16le').dump.end_with?(".force_encoding(\"UTF-16LE\")").should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "keeps origin encoding" do
|
||||||
|
"foo".encode("ISO-8859-1").dump.encoding.should == Encoding::ISO_8859_1
|
||||||
|
"foo".encode('windows-1251').dump.encoding.should == Encoding::Windows_1251
|
||||||
|
1.chr.dump.encoding.should == Encoding::US_ASCII
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ describe 'String#-@' do
|
||||||
input = 'foo'.freeze
|
input = 'foo'.freeze
|
||||||
output = -input
|
output = -input
|
||||||
|
|
||||||
output.equal?(input).should == true
|
output.should equal(input)
|
||||||
output.frozen?.should == true
|
output.frozen?.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ describe 'String#-@' do
|
||||||
output = -input
|
output = -input
|
||||||
|
|
||||||
output.frozen?.should == true
|
output.frozen?.should == true
|
||||||
|
output.should_not equal(input)
|
||||||
output.should == 'foo'
|
output.should == 'foo'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,11 +31,25 @@ describe 'String#-@' do
|
||||||
(-"unfrozen string").should equal(-"unfrozen string")
|
(-"unfrozen string").should equal(-"unfrozen string")
|
||||||
(-"unfrozen string").should_not equal(-"another unfrozen string")
|
(-"unfrozen string").should_not equal(-"another unfrozen string")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.5"..."2.6" do
|
||||||
|
it "does not deduplicate already frozen strings" do
|
||||||
|
dynamic = %w(this string is frozen).join(' ').freeze
|
||||||
|
|
||||||
|
dynamic.should_not equal("this string is frozen".freeze)
|
||||||
|
|
||||||
|
(-dynamic).should_not equal("this string is frozen".freeze)
|
||||||
|
(-dynamic).should_not equal(-"this string is frozen".freeze)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.6" do
|
||||||
it "deduplicates frozen strings" do
|
it "deduplicates frozen strings" do
|
||||||
dynamic = %w(this string is frozen).join(' ').freeze
|
dynamic = %w(this string is frozen).join(' ').freeze
|
||||||
|
|
||||||
dynamic.should_not equal("this string is frozen".freeze)
|
dynamic.should_not equal("this string is frozen".freeze)
|
||||||
|
|
||||||
(-dynamic).should equal("this string is frozen".freeze)
|
(-dynamic).should equal("this string is frozen".freeze)
|
||||||
(-dynamic).should equal(-"this string is frozen".freeze)
|
(-dynamic).should equal(-"this string is frozen".freeze)
|
||||||
end
|
end
|
||||||
|
|
451
spec/ruby/core/string/undump_spec.rb
Normal file
451
spec/ruby/core/string/undump_spec.rb
Normal file
|
@ -0,0 +1,451 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require_relative '../../spec_helper'
|
||||||
|
require_relative 'fixtures/classes'
|
||||||
|
|
||||||
|
ruby_version_is '2.5' do
|
||||||
|
describe "String#undump" do
|
||||||
|
it "taints the result if self is tainted" do
|
||||||
|
'"foo"'.taint.undump.tainted?.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "untrusts the result if self is untrusted" do
|
||||||
|
'"foo"'.untrust.undump.untrusted?.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not take into account if a string is frozen" do
|
||||||
|
'"foo"'.freeze.undump.frozen?.should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "always returns String instance" do
|
||||||
|
StringSpecs::MyString.new('"foo"').undump.should be_an_instance_of(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "strips outer \"" do
|
||||||
|
'"foo"'.undump.should == 'foo'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with special characters in \\<char> notation replaced with the characters" do
|
||||||
|
[ ['"\\a"', "\a"],
|
||||||
|
['"\\b"', "\b"],
|
||||||
|
['"\\t"', "\t"],
|
||||||
|
['"\\n"', "\n"],
|
||||||
|
['"\\v"', "\v"],
|
||||||
|
['"\\f"', "\f"],
|
||||||
|
['"\\r"', "\r"],
|
||||||
|
['"\\e"', "\e"]
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with unescaped sequencies \" and \\" do
|
||||||
|
[ ['"\\""' , "\""],
|
||||||
|
['"\\\\"', "\\"]
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with unescaped sequences \\#<char> when # is followed by $, @, {" do
|
||||||
|
[ ['"\\#$PATH"', "\#$PATH"],
|
||||||
|
['"\\#@a"', "\#@a"],
|
||||||
|
['"\\#@@a"', "\#@@a"],
|
||||||
|
['"\\#{a}"', "\#{a}"]
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with # not escaped when followed by any other character" do
|
||||||
|
[ ['"#"', '#'],
|
||||||
|
['"#1"', '#1']
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with printable non-alphanumeric characters" do
|
||||||
|
[ ['" "', ' '],
|
||||||
|
['"!"', '!'],
|
||||||
|
['"$"', '$'],
|
||||||
|
['"%"', '%'],
|
||||||
|
['"&"', '&'],
|
||||||
|
['"\'"', '\''],
|
||||||
|
['"("', '('],
|
||||||
|
['")"', ')'],
|
||||||
|
['"*"', '*'],
|
||||||
|
['"+"', '+'],
|
||||||
|
['","', ','],
|
||||||
|
['"-"', '-'],
|
||||||
|
['"."', '.'],
|
||||||
|
['"/"', '/'],
|
||||||
|
['":"', ':'],
|
||||||
|
['";"', ';'],
|
||||||
|
['"<"', '<'],
|
||||||
|
['"="', '='],
|
||||||
|
['">"', '>'],
|
||||||
|
['"?"', '?'],
|
||||||
|
['"@"', '@'],
|
||||||
|
['"["', '['],
|
||||||
|
['"]"', ']'],
|
||||||
|
['"^"', '^'],
|
||||||
|
['"_"', '_'],
|
||||||
|
['"`"', '`'],
|
||||||
|
['"{"', '{'],
|
||||||
|
['"|"', '|'],
|
||||||
|
['"}"', '}'],
|
||||||
|
['"~"', '~']
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with numeric characters unescaped" do
|
||||||
|
[ ['"0"', "0"],
|
||||||
|
['"1"', "1"],
|
||||||
|
['"2"', "2"],
|
||||||
|
['"3"', "3"],
|
||||||
|
['"4"', "4"],
|
||||||
|
['"5"', "5"],
|
||||||
|
['"6"', "6"],
|
||||||
|
['"7"', "7"],
|
||||||
|
['"8"', "8"],
|
||||||
|
['"9"', "9"],
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with upper-case alpha characters unescaped" do
|
||||||
|
[ ['"A"', 'A'],
|
||||||
|
['"B"', 'B'],
|
||||||
|
['"C"', 'C'],
|
||||||
|
['"D"', 'D'],
|
||||||
|
['"E"', 'E'],
|
||||||
|
['"F"', 'F'],
|
||||||
|
['"G"', 'G'],
|
||||||
|
['"H"', 'H'],
|
||||||
|
['"I"', 'I'],
|
||||||
|
['"J"', 'J'],
|
||||||
|
['"K"', 'K'],
|
||||||
|
['"L"', 'L'],
|
||||||
|
['"M"', 'M'],
|
||||||
|
['"N"', 'N'],
|
||||||
|
['"O"', 'O'],
|
||||||
|
['"P"', 'P'],
|
||||||
|
['"Q"', 'Q'],
|
||||||
|
['"R"', 'R'],
|
||||||
|
['"S"', 'S'],
|
||||||
|
['"T"', 'T'],
|
||||||
|
['"U"', 'U'],
|
||||||
|
['"V"', 'V'],
|
||||||
|
['"W"', 'W'],
|
||||||
|
['"X"', 'X'],
|
||||||
|
['"Y"', 'Y'],
|
||||||
|
['"Z"', 'Z']
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with lower-case alpha characters unescaped" do
|
||||||
|
[ ['"a"', 'a'],
|
||||||
|
['"b"', 'b'],
|
||||||
|
['"c"', 'c'],
|
||||||
|
['"d"', 'd'],
|
||||||
|
['"e"', 'e'],
|
||||||
|
['"f"', 'f'],
|
||||||
|
['"g"', 'g'],
|
||||||
|
['"h"', 'h'],
|
||||||
|
['"i"', 'i'],
|
||||||
|
['"j"', 'j'],
|
||||||
|
['"k"', 'k'],
|
||||||
|
['"l"', 'l'],
|
||||||
|
['"m"', 'm'],
|
||||||
|
['"n"', 'n'],
|
||||||
|
['"o"', 'o'],
|
||||||
|
['"p"', 'p'],
|
||||||
|
['"q"', 'q'],
|
||||||
|
['"r"', 'r'],
|
||||||
|
['"s"', 's'],
|
||||||
|
['"t"', 't'],
|
||||||
|
['"u"', 'u'],
|
||||||
|
['"v"', 'v'],
|
||||||
|
['"w"', 'w'],
|
||||||
|
['"x"', 'x'],
|
||||||
|
['"y"', 'y'],
|
||||||
|
['"z"', 'z']
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with \\x notation replaced with non-printing ASCII character" do
|
||||||
|
[ ['"\\x00"', 0000.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x01"', 0001.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x02"', 0002.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x03"', 0003.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x04"', 0004.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x05"', 0005.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x06"', 0006.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x0E"', 0016.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x0F"', 0017.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x10"', 0020.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x11"', 0021.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x12"', 0022.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x13"', 0023.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x14"', 0024.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x15"', 0025.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x16"', 0026.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x17"', 0027.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x18"', 0030.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x19"', 0031.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x1A"', 0032.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x1C"', 0034.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x1D"', 0035.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x1E"', 0036.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x1F"', 0037.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x7F"', 0177.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x80"', 0200.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x81"', 0201.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x82"', 0202.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x83"', 0203.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x84"', 0204.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x85"', 0205.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x86"', 0206.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x87"', 0207.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x88"', 0210.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x89"', 0211.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x8A"', 0212.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x8B"', 0213.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x8C"', 0214.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x8D"', 0215.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x8E"', 0216.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x8F"', 0217.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x90"', 0220.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x91"', 0221.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x92"', 0222.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x93"', 0223.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x94"', 0224.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x95"', 0225.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x96"', 0226.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x97"', 0227.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x98"', 0230.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x99"', 0231.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x9A"', 0232.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x9B"', 0233.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x9C"', 0234.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x9D"', 0235.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x9E"', 0236.chr.force_encoding('utf-8')],
|
||||||
|
['"\\x9F"', 0237.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA0"', 0240.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA1"', 0241.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA2"', 0242.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA3"', 0243.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA4"', 0244.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA5"', 0245.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA6"', 0246.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA7"', 0247.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA8"', 0250.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xA9"', 0251.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xAA"', 0252.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xAB"', 0253.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xAC"', 0254.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xAD"', 0255.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xAE"', 0256.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xAF"', 0257.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB0"', 0260.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB1"', 0261.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB2"', 0262.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB3"', 0263.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB4"', 0264.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB5"', 0265.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB6"', 0266.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB7"', 0267.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB8"', 0270.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xB9"', 0271.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xBA"', 0272.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xBB"', 0273.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xBC"', 0274.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xBD"', 0275.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xBE"', 0276.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xBF"', 0277.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC0"', 0300.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC1"', 0301.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC2"', 0302.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC3"', 0303.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC4"', 0304.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC5"', 0305.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC6"', 0306.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC7"', 0307.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC8"', 0310.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xC9"', 0311.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xCA"', 0312.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xCB"', 0313.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xCC"', 0314.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xCD"', 0315.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xCE"', 0316.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xCF"', 0317.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD0"', 0320.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD1"', 0321.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD2"', 0322.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD3"', 0323.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD4"', 0324.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD5"', 0325.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD6"', 0326.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD7"', 0327.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD8"', 0330.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xD9"', 0331.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xDA"', 0332.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xDB"', 0333.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xDC"', 0334.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xDD"', 0335.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xDE"', 0336.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xDF"', 0337.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE0"', 0340.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE1"', 0341.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE2"', 0342.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE3"', 0343.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE4"', 0344.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE5"', 0345.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE6"', 0346.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE7"', 0347.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE8"', 0350.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xE9"', 0351.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xEA"', 0352.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xEB"', 0353.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xEC"', 0354.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xED"', 0355.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xEE"', 0356.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xEF"', 0357.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF0"', 0360.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF1"', 0361.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF2"', 0362.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF3"', 0363.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF4"', 0364.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF5"', 0365.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF6"', 0366.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF7"', 0367.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF8"', 0370.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xF9"', 0371.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xFA"', 0372.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xFB"', 0373.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xFC"', 0374.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xFD"', 0375.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xFE"', 0376.chr.force_encoding('utf-8')],
|
||||||
|
['"\\xFF"', 0377.chr.force_encoding('utf-8')]
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with \\u{} notation replaced with multi-byte UTF-8 characters" do
|
||||||
|
[ ['"\u{80}"', 0200.chr('utf-8')],
|
||||||
|
['"\u{81}"', 0201.chr('utf-8')],
|
||||||
|
['"\u{82}"', 0202.chr('utf-8')],
|
||||||
|
['"\u{83}"', 0203.chr('utf-8')],
|
||||||
|
['"\u{84}"', 0204.chr('utf-8')],
|
||||||
|
['"\u{86}"', 0206.chr('utf-8')],
|
||||||
|
['"\u{87}"', 0207.chr('utf-8')],
|
||||||
|
['"\u{88}"', 0210.chr('utf-8')],
|
||||||
|
['"\u{89}"', 0211.chr('utf-8')],
|
||||||
|
['"\u{8a}"', 0212.chr('utf-8')],
|
||||||
|
['"\u{8b}"', 0213.chr('utf-8')],
|
||||||
|
['"\u{8c}"', 0214.chr('utf-8')],
|
||||||
|
['"\u{8d}"', 0215.chr('utf-8')],
|
||||||
|
['"\u{8e}"', 0216.chr('utf-8')],
|
||||||
|
['"\u{8f}"', 0217.chr('utf-8')],
|
||||||
|
['"\u{90}"', 0220.chr('utf-8')],
|
||||||
|
['"\u{91}"', 0221.chr('utf-8')],
|
||||||
|
['"\u{92}"', 0222.chr('utf-8')],
|
||||||
|
['"\u{93}"', 0223.chr('utf-8')],
|
||||||
|
['"\u{94}"', 0224.chr('utf-8')],
|
||||||
|
['"\u{95}"', 0225.chr('utf-8')],
|
||||||
|
['"\u{96}"', 0226.chr('utf-8')],
|
||||||
|
['"\u{97}"', 0227.chr('utf-8')],
|
||||||
|
['"\u{98}"', 0230.chr('utf-8')],
|
||||||
|
['"\u{99}"', 0231.chr('utf-8')],
|
||||||
|
['"\u{9a}"', 0232.chr('utf-8')],
|
||||||
|
['"\u{9b}"', 0233.chr('utf-8')],
|
||||||
|
['"\u{9c}"', 0234.chr('utf-8')],
|
||||||
|
['"\u{9d}"', 0235.chr('utf-8')],
|
||||||
|
['"\u{9e}"', 0236.chr('utf-8')],
|
||||||
|
['"\u{9f}"', 0237.chr('utf-8')],
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a string with \\uXXXX notation replaced with multi-byte UTF-8 characters" do
|
||||||
|
[ ['"\u0080"', 0200.chr('utf-8')],
|
||||||
|
['"\u0081"', 0201.chr('utf-8')],
|
||||||
|
['"\u0082"', 0202.chr('utf-8')],
|
||||||
|
['"\u0083"', 0203.chr('utf-8')],
|
||||||
|
['"\u0084"', 0204.chr('utf-8')],
|
||||||
|
['"\u0086"', 0206.chr('utf-8')],
|
||||||
|
['"\u0087"', 0207.chr('utf-8')],
|
||||||
|
['"\u0088"', 0210.chr('utf-8')],
|
||||||
|
['"\u0089"', 0211.chr('utf-8')],
|
||||||
|
['"\u008a"', 0212.chr('utf-8')],
|
||||||
|
['"\u008b"', 0213.chr('utf-8')],
|
||||||
|
['"\u008c"', 0214.chr('utf-8')],
|
||||||
|
['"\u008d"', 0215.chr('utf-8')],
|
||||||
|
['"\u008e"', 0216.chr('utf-8')],
|
||||||
|
['"\u008f"', 0217.chr('utf-8')],
|
||||||
|
['"\u0090"', 0220.chr('utf-8')],
|
||||||
|
['"\u0091"', 0221.chr('utf-8')],
|
||||||
|
['"\u0092"', 0222.chr('utf-8')],
|
||||||
|
['"\u0093"', 0223.chr('utf-8')],
|
||||||
|
['"\u0094"', 0224.chr('utf-8')],
|
||||||
|
['"\u0095"', 0225.chr('utf-8')],
|
||||||
|
['"\u0096"', 0226.chr('utf-8')],
|
||||||
|
['"\u0097"', 0227.chr('utf-8')],
|
||||||
|
['"\u0098"', 0230.chr('utf-8')],
|
||||||
|
['"\u0099"', 0231.chr('utf-8')],
|
||||||
|
['"\u009a"', 0232.chr('utf-8')],
|
||||||
|
['"\u009b"', 0233.chr('utf-8')],
|
||||||
|
['"\u009c"', 0234.chr('utf-8')],
|
||||||
|
['"\u009d"', 0235.chr('utf-8')],
|
||||||
|
['"\u009e"', 0236.chr('utf-8')],
|
||||||
|
['"\u009f"', 0237.chr('utf-8')],
|
||||||
|
].should be_computed_by(:undump)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "undumps correctly string produced from non ASCII-compatible one" do
|
||||||
|
s = "\u{876}".encode('utf-16be')
|
||||||
|
s.dump.undump.should == s
|
||||||
|
|
||||||
|
'"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "keeps origin encoding" do
|
||||||
|
'"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1
|
||||||
|
'"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Limitations" do
|
||||||
|
it "cannot undump non ASCII-compatible string" do
|
||||||
|
-> { '"foo"'.encode('utf-16le').undump }.should raise_error(Encoding::CompatibilityError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "invalid dump" do
|
||||||
|
it "raises RuntimeError exception if wrapping \" are missing" do
|
||||||
|
-> { 'foo'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
|
||||||
|
-> { '"foo'.undump }.should raise_error(RuntimeError, /unterminated dumped string/)
|
||||||
|
-> { 'foo"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
|
||||||
|
-> { "'foo'".undump }.should raise_error(RuntimeError, /invalid dumped string/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises RuntimeError if there is incorrect \\x sequence" do
|
||||||
|
-> { '"\x"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
|
||||||
|
-> { '"\\x3y"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises RuntimeError in there is incorrect \\u sequence" do
|
||||||
|
-> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
|
||||||
|
-> { '"\\u{"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
|
||||||
|
-> { '"\\u{3042"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
|
||||||
|
-> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises RuntimeError if there is malformed dump of non ASCII-compatible string" do
|
||||||
|
-> { '"".force_encoding("ASCII-8BIT"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
|
||||||
|
-> { '"".force_encoding("Unknown")'.undump }.should raise_error(RuntimeError, /dumped string has unknown encoding name/)
|
||||||
|
-> { '"".force_encoding()'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises RuntimeError if string contains \0 character" do
|
||||||
|
-> { "\"foo\0\"".undump }.should raise_error(RuntimeError, /string contains null byte/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises RuntimeError if string contains non ASCII character" do
|
||||||
|
-> { "\"\u3042\"".undump }.should raise_error(RuntimeError, /non-ASCII character detected/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises RuntimeError if there are some excessive \"" do
|
||||||
|
-> { '" "" "'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,4 +9,14 @@ describe 'Thread::Backtrace::Location#base_label' do
|
||||||
it 'returns the base label of the call frame' do
|
it 'returns the base label of the call frame' do
|
||||||
@frame.base_label.should == '<top (required)>'
|
@frame.base_label.should == '<top (required)>'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'when call frame is inside a block' do
|
||||||
|
before :each do
|
||||||
|
@frame = ThreadBacktraceLocationSpecs.block_location[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the name of the method that contains the block' do
|
||||||
|
@frame.base_label.should == 'block_location'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
require_relative '../../spec_helper'
|
require_relative '../../spec_helper'
|
||||||
|
|
||||||
describe 'TracePoint#parameters' do
|
ruby_version_is "2.6" do
|
||||||
it 'returns the parameters of block' do
|
describe 'TracePoint#parameters' do
|
||||||
f = proc {|x, y, z| }
|
it 'returns the parameters of block' do
|
||||||
parameters = nil
|
f = proc {|x, y, z| }
|
||||||
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
|
parameters = nil
|
||||||
f.call
|
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
|
||||||
parameters.should == [[:opt, :x], [:opt, :y], [:opt, :z]]
|
f.call
|
||||||
|
parameters.should == [[:opt, :x], [:opt, :y], [:opt, :z]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns the parameters of lambda block' do
|
it 'returns the parameters of lambda block' do
|
||||||
f = lambda {|x, y, z| }
|
f = lambda {|x, y, z| }
|
||||||
parameters = nil
|
parameters = nil
|
||||||
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
|
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
|
||||||
f.call(1, 2, 3)
|
f.call(1, 2, 3)
|
||||||
parameters.should == [[:req, :x], [:req, :y], [:req, :z]]
|
parameters.should == [[:req, :x], [:req, :y], [:req, :z]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -196,13 +196,9 @@ describe "The super keyword" do
|
||||||
Super::ZSuperWithRestReassigned::B.new.a("bar").should == ["foo"]
|
Super::ZSuperWithRestReassigned::B.new.a("bar").should == ["foo"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Don't run this spec on Appveyor because it uses old Ruby versions
|
# https://bugs.ruby-lang.org/issues/14279
|
||||||
# The specs ends with segfault on old versions so let's just disable it
|
it "wraps into array and passes along reassigned rest args with non-array scalar value" do
|
||||||
platform_is_not :windows do
|
Super::ZSuperWithRestReassignedWithScalar::B.new.a("bar").should == ["foo"]
|
||||||
# https://bugs.ruby-lang.org/issues/14279
|
|
||||||
it "wraps into array and passes along reassigned rest args with non-array scalar value" do
|
|
||||||
Super::ZSuperWithRestReassignedWithScalar::B.new.a("bar").should == ["foo"]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "invokes methods from a chain of anonymous modules" do
|
it "invokes methods from a chain of anonymous modules" do
|
||||||
|
|
|
@ -22,15 +22,12 @@ describe "Float#hash" do
|
||||||
it_behaves_like :resists_cve_2011_4815, '3.14'
|
it_behaves_like :resists_cve_2011_4815, '3.14'
|
||||||
end
|
end
|
||||||
|
|
||||||
# https://bugs.ruby-lang.org/issues/14420
|
describe "Rational#hash" do
|
||||||
guard_not -> { platform_is :windows and PlatformGuard.implementation?(:ruby) } do
|
it_behaves_like :resists_cve_2011_4815, 'Rational(1, 2)'
|
||||||
describe "Rational#hash" do
|
end
|
||||||
it_behaves_like :resists_cve_2011_4815, 'Rational(1, 2)'
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "Complex#hash" do
|
describe "Complex#hash" do
|
||||||
it_behaves_like :resists_cve_2011_4815, 'Complex(1, 2)'
|
it_behaves_like :resists_cve_2011_4815, 'Complex(1, 2)'
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "String#hash" do
|
describe "String#hash" do
|
||||||
|
|
|
@ -4,37 +4,31 @@ require "webrick"
|
||||||
require "stringio"
|
require "stringio"
|
||||||
require "net/http"
|
require "net/http"
|
||||||
|
|
||||||
guard -> {
|
describe "WEBrick" do
|
||||||
ruby_version_is "2.3.7"..."2.4" or
|
describe "resists CVE-2017-17742" do
|
||||||
ruby_version_is "2.4.4"..."2.5" or
|
it "for a response splitting headers" do
|
||||||
ruby_version_is "2.5.1"
|
config = WEBrick::Config::HTTP
|
||||||
} do
|
res = WEBrick::HTTPResponse.new config
|
||||||
describe "WEBrick" do
|
res['X-header'] = "malicious\r\nCookie: hack"
|
||||||
describe "resists CVE-2017-17742" do
|
io = StringIO.new
|
||||||
it "for a response splitting headers" do
|
res.send_response io
|
||||||
config = WEBrick::Config::HTTP
|
io.rewind
|
||||||
res = WEBrick::HTTPResponse.new config
|
res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
|
||||||
res['X-header'] = "malicious\r\nCookie: hack"
|
res.code.should == '500'
|
||||||
io = StringIO.new
|
io.string.should_not =~ /hack/
|
||||||
res.send_response io
|
end
|
||||||
io.rewind
|
|
||||||
res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
|
|
||||||
res.code.should == '500'
|
|
||||||
io.string.should_not =~ /hack/
|
|
||||||
end
|
|
||||||
|
|
||||||
it "for a response splitting cookie headers" do
|
it "for a response splitting cookie headers" do
|
||||||
user_input = "malicious\r\nCookie: hack"
|
user_input = "malicious\r\nCookie: hack"
|
||||||
config = WEBrick::Config::HTTP
|
config = WEBrick::Config::HTTP
|
||||||
res = WEBrick::HTTPResponse.new config
|
res = WEBrick::HTTPResponse.new config
|
||||||
res.cookies << WEBrick::Cookie.new('author', user_input)
|
res.cookies << WEBrick::Cookie.new('author', user_input)
|
||||||
io = StringIO.new
|
io = StringIO.new
|
||||||
res.send_response io
|
res.send_response io
|
||||||
io.rewind
|
io.rewind
|
||||||
res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
|
res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
|
||||||
res.code.should == '500'
|
res.code.should == '500'
|
||||||
io.string.should_not =~ /hack/
|
io.string.should_not =~ /hack/
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,58 +2,52 @@ require_relative '../spec_helper'
|
||||||
|
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
|
|
||||||
guard -> {
|
describe "CVE-2018-6914 is resisted by" do
|
||||||
ruby_version_is "2.3.7"..."2.4" or
|
before :all do
|
||||||
ruby_version_is "2.4.4"..."2.5" or
|
@traversal_path = Array.new(Dir.pwd.split('/').count, '..').join('/') + Dir.pwd + '/'
|
||||||
ruby_version_is "2.5.1"
|
@traversal_path.delete!(':') if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||||
} do
|
end
|
||||||
describe "CVE-2018-6914 is resisted by" do
|
|
||||||
before :all do
|
|
||||||
@traversal_path = Array.new(Dir.pwd.split('/').count, '..').join('/') + Dir.pwd + '/'
|
|
||||||
@traversal_path.delete!(':') if /mswin|mingw/ =~ RUBY_PLATFORM
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Tempfile.open by deleting separators" do
|
it "Tempfile.open by deleting separators" do
|
||||||
begin
|
begin
|
||||||
expect = Dir.glob(@traversal_path + '*').count
|
|
||||||
t = Tempfile.open([@traversal_path, 'foo'])
|
|
||||||
actual = Dir.glob(@traversal_path + '*').count
|
|
||||||
actual.should == expect
|
|
||||||
ensure
|
|
||||||
t.close!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Tempfile.new by deleting separators" do
|
|
||||||
begin
|
|
||||||
expect = Dir.glob(@traversal_path + '*').count
|
|
||||||
t = Tempfile.new(@traversal_path + 'foo')
|
|
||||||
actual = Dir.glob(@traversal_path + '*').count
|
|
||||||
actual.should == expect
|
|
||||||
ensure
|
|
||||||
t.close!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Tempfile.create by deleting separators" do
|
|
||||||
expect = Dir.glob(@traversal_path + '*').count
|
expect = Dir.glob(@traversal_path + '*').count
|
||||||
Tempfile.create(@traversal_path + 'foo')
|
t = Tempfile.open([@traversal_path, 'foo'])
|
||||||
actual = Dir.glob(@traversal_path + '*').count
|
|
||||||
actual.should == expect
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Dir.mktmpdir by deleting separators" do
|
|
||||||
expect = Dir.glob(@traversal_path + '*').count
|
|
||||||
Dir.mktmpdir(@traversal_path + 'foo')
|
|
||||||
actual = Dir.glob(@traversal_path + '*').count
|
|
||||||
actual.should == expect
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Dir.mktmpdir with an array by deleting separators" do
|
|
||||||
expect = Dir.glob(@traversal_path + '*').count
|
|
||||||
Dir.mktmpdir([@traversal_path, 'foo'])
|
|
||||||
actual = Dir.glob(@traversal_path + '*').count
|
actual = Dir.glob(@traversal_path + '*').count
|
||||||
actual.should == expect
|
actual.should == expect
|
||||||
|
ensure
|
||||||
|
t.close!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "Tempfile.new by deleting separators" do
|
||||||
|
begin
|
||||||
|
expect = Dir.glob(@traversal_path + '*').count
|
||||||
|
t = Tempfile.new(@traversal_path + 'foo')
|
||||||
|
actual = Dir.glob(@traversal_path + '*').count
|
||||||
|
actual.should == expect
|
||||||
|
ensure
|
||||||
|
t.close!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Tempfile.create by deleting separators" do
|
||||||
|
expect = Dir.glob(@traversal_path + '*').count
|
||||||
|
Tempfile.create(@traversal_path + 'foo')
|
||||||
|
actual = Dir.glob(@traversal_path + '*').count
|
||||||
|
actual.should == expect
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Dir.mktmpdir by deleting separators" do
|
||||||
|
expect = Dir.glob(@traversal_path + '*').count
|
||||||
|
Dir.mktmpdir(@traversal_path + 'foo')
|
||||||
|
actual = Dir.glob(@traversal_path + '*').count
|
||||||
|
actual.should == expect
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Dir.mktmpdir with an array by deleting separators" do
|
||||||
|
expect = Dir.glob(@traversal_path + '*').count
|
||||||
|
Dir.mktmpdir([@traversal_path, 'foo'])
|
||||||
|
actual = Dir.glob(@traversal_path + '*').count
|
||||||
|
actual.should == expect
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,53 +1,47 @@
|
||||||
require_relative '../spec_helper'
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
guard -> {
|
describe "CVE-2018-8780 is resisted by" do
|
||||||
ruby_version_is "2.3.7"..."2.4" or
|
before :all do
|
||||||
ruby_version_is "2.4.4"..."2.5" or
|
@root = File.realpath(tmp(""))
|
||||||
ruby_version_is "2.5.1"
|
end
|
||||||
} do
|
|
||||||
describe "CVE-2018-8780 is resisted by" do
|
|
||||||
before :all do
|
|
||||||
@root = File.realpath(tmp(""))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Dir.glob by raising an exception when there is a NUL byte" do
|
it "Dir.glob by raising an exception when there is a NUL byte" do
|
||||||
|
lambda {
|
||||||
|
Dir.glob([[@root, File.join(@root, "*")].join("\0")])
|
||||||
|
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Dir.entries by raising an exception when there is a NUL byte" do
|
||||||
|
lambda {
|
||||||
|
Dir.entries(@root+"\0")
|
||||||
|
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Dir.foreach by raising an exception when there is a NUL byte" do
|
||||||
|
lambda {
|
||||||
|
Dir.foreach(@root+"\0").to_a
|
||||||
|
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.4" do
|
||||||
|
it "Dir.empty? by raising an exception when there is a NUL byte" do
|
||||||
lambda {
|
lambda {
|
||||||
Dir.glob([[@root, File.join(@root, "*")].join("\0")])
|
Dir.empty?(@root+"\0")
|
||||||
|
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.5" do
|
||||||
|
it "Dir.children by raising an exception when there is a NUL byte" do
|
||||||
|
lambda {
|
||||||
|
Dir.children(@root+"\0")
|
||||||
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "Dir.entries by raising an exception when there is a NUL byte" do
|
it "Dir.each_child by raising an exception when there is a NUL byte" do
|
||||||
lambda {
|
lambda {
|
||||||
Dir.entries(@root+"\0")
|
Dir.each_child(@root+"\0").to_a
|
||||||
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "Dir.foreach by raising an exception when there is a NUL byte" do
|
|
||||||
lambda {
|
|
||||||
Dir.foreach(@root+"\0").to_a
|
|
||||||
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
|
||||||
end
|
|
||||||
|
|
||||||
ruby_version_is "2.5" do
|
|
||||||
it "Dir.children by raising an exception when there is a NUL byte" do
|
|
||||||
lambda {
|
|
||||||
Dir.children(@root+"\0")
|
|
||||||
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Dir.each_child by raising an exception when there is a NUL byte" do
|
|
||||||
lambda {
|
|
||||||
Dir.each_child(@root+"\0").to_a
|
|
||||||
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ruby_version_is "2.4" do
|
|
||||||
it "Dir.empty? by raising an exception when there is a NUL byte" do
|
|
||||||
lambda {
|
|
||||||
Dir.empty?(@root+"\0")
|
|
||||||
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue