1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63652 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2018-06-13 21:41:45 +00:00
parent 78890babe7
commit 67078e81f5
24 changed files with 1220 additions and 313 deletions

View file

@ -3,16 +3,20 @@ version: "{build}"
clone_depth: 5
init:
# 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
- if %ruby_version%==_trunk (
appveyor DownloadFile https://ci.appveyor.com/api/projects/MSP-Greg/ruby-loco/artifacts/ruby_trunk.7z -FileName C:\ruby_trunk.7z &
7z x C:\ruby_trunk.7z -oC:\ruby_trunk & C:\ruby_trunk\trunk_msys2.cmd)
- ps: |
if ($env:ruby_version -eq '_trunk') {
$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:
matrix:
- RUBY_VERSION: 23-x64
- RUBY_VERSION: 24-x64
- RUBY_VERSION: _trunk # So the folder name is ruby_trunk
- ruby_version: 24-x64
- ruby_version: 25-x64
- ruby_version: _trunk # So the folder name is ruby_trunk
install:
- git clone https://github.com/ruby/mspec.git ../mspec
build: off

View file

@ -2,12 +2,11 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Enumerable#all?" do
before :each do
@enum = EnumerableSpecs::Numerous.new
@empty = EnumerableSpecs::Empty.new()
@enum1 = [0, 1, 2, -1]
@enum2 = [nil, false, true]
@enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1)
@enum2 = EnumerableSpecs::Numerous.new(nil, false, true)
end
it "always returns true on empty enumeration" do
@ -21,6 +20,21 @@ describe "Enumerable#all?" do
{}.all? { nil }.should == true
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
lambda {
EnumerableSpecs::ThrowingEach.new.all?
@ -58,16 +72,6 @@ describe "Enumerable#all?" do
multi = EnumerableSpecs::YieldsMultiWithFalse.new
multi.all?.should be_true
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
describe "with block" do
@ -117,14 +121,79 @@ describe "Enumerable#all?" do
it "gathers initial args as elements when each yields multiple" do
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
it "yields multiple arguments when each yields multiple" do
multi = EnumerableSpecs::YieldsMulti.new
yielded = []
multi.all? {|e, i| yielded << [e, i] }
yielded.should == [[1, 2], [3, 4], [6, 7]]
multi.all? { |*args| yielded << args }.should == true
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

View file

@ -4,9 +4,9 @@ require_relative 'fixtures/classes'
describe "Enumerable#any?" do
before :each do
@enum = EnumerableSpecs::Numerous.new
@empty = EnumerableSpecs::Empty.new()
@enum1 = [0, 1, 2, -1]
@enum2 = [nil, false, true]
@empty = EnumerableSpecs::Empty.new
@enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1)
@enum2 = EnumerableSpecs::Numerous.new(nil, false, true)
end
it "always returns false on empty enumeration" do
@ -86,7 +86,7 @@ describe "Enumerable#any?" do
@enum2.any? { |i| i == nil }.should == true
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? { nil }.should == false
@ -134,32 +134,21 @@ describe "Enumerable#any?" do
it "gathers initial args as elements when each yields multiple" do
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
it "yields multiple arguments when each yields multiple" do
multi = EnumerableSpecs::YieldsMulti.new
yielded = []
multi.any? {|e, i| yielded << [e, i] }
yielded.should == [[1, 2]]
multi.any? { |*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
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
pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
@enum1.any?(pattern).should == true
@ -195,7 +184,7 @@ describe "Enumerable#any?" do
{a: 1, b: 2}.any?(pattern).should == true
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 }
@enum1.any?(pattern).should == false
pattern.yielded.should == [[0], [1], [2], [-1]]
@ -204,7 +193,7 @@ describe "Enumerable#any?" do
{a: 1}.any?(pattern).should == false
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" }
lambda {
@enum.any?(pattern)
@ -212,13 +201,10 @@ describe "Enumerable#any?" do
end
it "calls the pattern with gathered array when yielded with multiple arguments" do
multi = EnumerableSpecs::YieldsMulti.new
pattern = EnumerableSpecs::Pattern.new { false }
EnumerableSpecs::YieldsMixed2.new.any?(pattern).should == false
pattern.yielded.should == EnumerableSpecs::YieldsMixed2.gathered_yields.map { |x| [x] }
pattern = EnumerableSpecs::Pattern.new { false }
{a: 1, b: 2}.any?(pattern).should == false
pattern.yielded.should == [[[:a, 1]], [[:b, 2]]]
multi.any?(pattern).should == false
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
end
end

View file

@ -328,4 +328,18 @@ module EnumerableSpecs
EnumerableMapping.new(self, block)
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

View file

@ -2,67 +2,164 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Enumerable#none?" 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
before :each do
@empty = EnumerableSpecs::Empty.new
@enum = EnumerableSpecs::Numerous.new
@enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1)
@enum2 = EnumerableSpecs::Numerous.new(nil, false, 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
it "always returns true on empty enumeration" do
@empty.none?.should == true
@empty.none? { true }.should == true
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
it "raises an ArgumentError when more than 1 argument is provided" do
lambda { @enum.none?(1, 2, 3) }.should raise_error(ArgumentError)
lambda { [].none?(1, 2, 3) }.should raise_error(ArgumentError)
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
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.none?(Float).should == true
[nil, false, true].none?(NilClass).should == false
describe 'when given a pattern argument' do
it "calls `===` on the pattern the return value " do
pattern = EnumerableSpecs::Pattern.new { |x| x == 3 }
@enum1.none?(pattern).should == true
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
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

View file

@ -2,44 +2,44 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Enumerable#one?" do
describe "when passed a block" do
it "returns true if block returns true once" do
[:a, :b, :c].one? { |s| s == :a }.should be_true
end
before :each do
@empty = EnumerableSpecs::Empty.new
@enum = EnumerableSpecs::Numerous.new
@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
[:a, :b, :c].one? { |s| s == :a || s == :b }.should be_false
end
it "always returns false on empty enumeration" do
@empty.one?.should == false
@empty.one? { true }.should == false
end
it "returns false if the block only returns false" do
[:a, :b, :c].one? { |s| s == :d }.should be_false
end
it "raises an ArgumentError when more than 1 argument is provided" do
lambda { @enum.one?(1, 2, 3) }.should raise_error(ArgumentError)
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
# This spec doesn't spec what it says it does
multi = EnumerableSpecs::YieldsMulti.new
multi.one? {|e| e == 1 }.should be_true
end
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
ruby_version_is ""..."2.5" do
it "raises an ArgumentError when any arguments provided" do
lambda { @enum.one?(Proc.new {}) }.should raise_error(ArgumentError)
lambda { @enum.one?(nil) }.should raise_error(ArgumentError)
lambda { @empty.one?(1) }.should raise_error(ArgumentError)
lambda { @enum.one?(1) {} }.should raise_error(ArgumentError)
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
[false, nil, true].one?.should be_true
end
@ -57,4 +57,111 @@ describe "Enumerable#one?" do
multi.one?.should be_false
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

View file

@ -60,6 +60,25 @@ describe "Kernel#autoload" do
ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "#{frozen_error_class} - nil"
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
describe "Kernel#autoload?" do
@ -107,6 +126,25 @@ describe "Kernel.autoload" do
p.should_receive(:to_path).and_return @non_existent
Kernel.autoload :KSAutoloadAA, p
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
describe "Kernel.autoload?" do

View file

@ -0,0 +1,9 @@
module KernelSpecs
module AutoloadMethod
module AutoloadFromIncludedModule
def self.loaded
:autoload_from_included_module
end
end
end
end

View file

@ -0,0 +1,9 @@
module KernelSpecs
module AutoloadMethod2
module AutoloadFromIncludedModule2
def self.loaded
:autoload_from_included_module2
end
end
end
end

View file

@ -378,6 +378,49 @@ module KernelSpecs
[3, 4]
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
class EvalSpecs

View 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

View 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

View file

@ -76,4 +76,60 @@ describe "Kernel#warn" do
warn("")
}.should output(nil, /\n/)
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

View file

@ -1,29 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/then'
ruby_version_is "2.5" do
describe "Kernel#yield_self" do
it "yields self" do
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
it_behaves_like :kernel_then, :yield_self
end
end

View file

@ -13,10 +13,18 @@ describe "String#dump" do
"foo\n".untrust.dump.untrusted?.should == true
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
StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString)
end
it "wraps string with \"" do
"foo".dump.should == '"foo"'
end
it "returns a string with special characters replaced with \\<char> notation" do
[ ["\a", '"\\a"'],
["\b", '"\\b"'],
@ -35,10 +43,11 @@ describe "String#dump" do
].should be_computed_by(:dump)
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)
end
@ -381,7 +390,7 @@ describe "String#dump" do
end
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"'],
[0201.chr('utf-8'), '"\u0081"'],
[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-16le').dump.end_with?(".force_encoding(\"UTF-16LE\")").should be_true
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

View file

@ -5,7 +5,7 @@ describe 'String#-@' do
input = 'foo'.freeze
output = -input
output.equal?(input).should == true
output.should equal(input)
output.frozen?.should == true
end
@ -14,6 +14,7 @@ describe 'String#-@' do
output = -input
output.frozen?.should == true
output.should_not equal(input)
output.should == 'foo'
end
@ -30,11 +31,25 @@ describe 'String#-@' do
(-"unfrozen string").should equal(-"unfrozen string")
(-"unfrozen string").should_not equal(-"another unfrozen string")
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
dynamic = %w(this string is frozen).join(' ').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)
end

View 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

View file

@ -9,4 +9,14 @@ describe 'Thread::Backtrace::Location#base_label' do
it 'returns the base label of the call frame' do
@frame.base_label.should == '<top (required)>'
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

View file

@ -1,21 +1,23 @@
require_relative '../../spec_helper'
describe 'TracePoint#parameters' do
it 'returns the parameters of block' do
f = proc {|x, y, z| }
parameters = nil
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
f.call
parameters.should == [[:opt, :x], [:opt, :y], [:opt, :z]]
ruby_version_is "2.6" do
describe 'TracePoint#parameters' do
it 'returns the parameters of block' do
f = proc {|x, y, z| }
parameters = nil
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
f.call
parameters.should == [[:opt, :x], [:opt, :y], [:opt, :z]]
end
end
end
it 'returns the parameters of lambda block' do
f = lambda {|x, y, z| }
parameters = nil
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
f.call(1, 2, 3)
parameters.should == [[:req, :x], [:req, :y], [:req, :z]]
it 'returns the parameters of lambda block' do
f = lambda {|x, y, z| }
parameters = nil
TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
f.call(1, 2, 3)
parameters.should == [[:req, :x], [:req, :y], [:req, :z]]
end
end
end
end

View file

@ -196,13 +196,9 @@ describe "The super keyword" do
Super::ZSuperWithRestReassigned::B.new.a("bar").should == ["foo"]
end
# Don't run this spec on Appveyor because it uses old Ruby versions
# The specs ends with segfault on old versions so let's just disable it
platform_is_not :windows do
# 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
# 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
it "invokes methods from a chain of anonymous modules" do

View file

@ -22,15 +22,12 @@ describe "Float#hash" do
it_behaves_like :resists_cve_2011_4815, '3.14'
end
# https://bugs.ruby-lang.org/issues/14420
guard_not -> { platform_is :windows and PlatformGuard.implementation?(:ruby) } do
describe "Rational#hash" do
it_behaves_like :resists_cve_2011_4815, 'Rational(1, 2)'
end
describe "Rational#hash" do
it_behaves_like :resists_cve_2011_4815, 'Rational(1, 2)'
end
describe "Complex#hash" do
it_behaves_like :resists_cve_2011_4815, 'Complex(1, 2)'
end
describe "Complex#hash" do
it_behaves_like :resists_cve_2011_4815, 'Complex(1, 2)'
end
describe "String#hash" do

View file

@ -4,37 +4,31 @@ require "webrick"
require "stringio"
require "net/http"
guard -> {
ruby_version_is "2.3.7"..."2.4" or
ruby_version_is "2.4.4"..."2.5" or
ruby_version_is "2.5.1"
} do
describe "WEBrick" do
describe "resists CVE-2017-17742" do
it "for a response splitting headers" do
config = WEBrick::Config::HTTP
res = WEBrick::HTTPResponse.new config
res['X-header'] = "malicious\r\nCookie: hack"
io = StringIO.new
res.send_response io
io.rewind
res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
res.code.should == '500'
io.string.should_not =~ /hack/
end
describe "WEBrick" do
describe "resists CVE-2017-17742" do
it "for a response splitting headers" do
config = WEBrick::Config::HTTP
res = WEBrick::HTTPResponse.new config
res['X-header'] = "malicious\r\nCookie: hack"
io = StringIO.new
res.send_response io
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
user_input = "malicious\r\nCookie: hack"
config = WEBrick::Config::HTTP
res = WEBrick::HTTPResponse.new config
res.cookies << WEBrick::Cookie.new('author', user_input)
io = StringIO.new
res.send_response io
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
user_input = "malicious\r\nCookie: hack"
config = WEBrick::Config::HTTP
res = WEBrick::HTTPResponse.new config
res.cookies << WEBrick::Cookie.new('author', user_input)
io = StringIO.new
res.send_response io
io.rewind
res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
res.code.should == '500'
io.string.should_not =~ /hack/
end
end
end

View file

@ -2,58 +2,52 @@ require_relative '../spec_helper'
require 'tempfile'
guard -> {
ruby_version_is "2.3.7"..."2.4" or
ruby_version_is "2.4.4"..."2.5" or
ruby_version_is "2.5.1"
} do
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
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
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
it "Tempfile.open by deleting separators" do
begin
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'])
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
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

View file

@ -1,53 +1,47 @@
require_relative '../spec_helper'
guard -> {
ruby_version_is "2.3.7"..."2.4" or
ruby_version_is "2.4.4"..."2.5" or
ruby_version_is "2.5.1"
} do
describe "CVE-2018-8780 is resisted by" do
before :all do
@root = File.realpath(tmp(""))
end
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 {
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/)
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 {
Dir.entries(@root+"\0")
Dir.each_child(@root+"\0").to_a
}.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.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