summaryrefslogtreecommitdiff
path: root/spec/ruby
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-10-27 10:48:40 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-10-27 10:48:40 +0000
commit3e6337b88b5255aba07b8f44de72cd5885f59465 (patch)
tree6146781aa381404b88ea4bfa2a44e75e8bc90d14 /spec/ruby
parentecc707e233a5577ea2048b3199d4baaf96c6b0f8 (diff)
Update to ruby/spec@8b743a3
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65388 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby')
-rw-r--r--spec/ruby/.travis.yml10
-rw-r--r--spec/ruby/core/array/eql_spec.rb6
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb5
-rw-r--r--spec/ruby/core/array/pack/a_spec.rb3
-rw-r--r--spec/ruby/core/array/pack/b_spec.rb3
-rw-r--r--spec/ruby/core/array/pack/h_spec.rb3
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb3
-rw-r--r--spec/ruby/core/array/pack/p_spec.rb47
-rw-r--r--spec/ruby/core/array/pack/shared/string.rb32
-rw-r--r--spec/ruby/core/array/pack/shared/taint.rb33
-rw-r--r--spec/ruby/core/array/pack/u_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/z_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/all_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/none_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/one_spec.rb1
-rw-r--r--spec/ruby/core/hash/slice_spec.rb21
-rw-r--r--spec/ruby/core/io/pread_spec.rb52
-rw-r--r--spec/ruby/core/io/pwrite_spec.rb45
-rw-r--r--spec/ruby/core/io/write_spec.rb11
-rw-r--r--spec/ruby/core/kernel/Complex_spec.rb4
-rw-r--r--spec/ruby/core/kernel/fixtures/classes.rb3
-rw-r--r--spec/ruby/core/kernel/shared/kind_of.rb13
-rw-r--r--spec/ruby/core/proc/element_reference_spec.rb13
-rw-r--r--spec/ruby/core/proc/fixtures/proc_aref.rb9
-rw-r--r--spec/ruby/core/proc/fixtures/proc_aref_frozen.rb10
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb18
-rw-r--r--spec/ruby/core/random/bytes_spec.rb19
-rw-r--r--spec/ruby/core/random/shared/bytes.rb17
-rw-r--r--spec/ruby/core/range/eql_spec.rb2
-rw-r--r--spec/ruby/core/range/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/string/chars_spec.rb3
-rw-r--r--spec/ruby/core/string/codepoints_spec.rb4
-rw-r--r--spec/ruby/core/string/each_grapheme_cluster_spec.rb11
-rw-r--r--spec/ruby/core/string/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/string/grapheme_clusters_spec.rb15
-rw-r--r--spec/ruby/core/string/lines_spec.rb2
-rw-r--r--spec/ruby/core/string/modulo_spec.rb17
-rw-r--r--spec/ruby/core/string/shared/grapheme_clusters.rb16
-rw-r--r--spec/ruby/core/string/slice_spec.rb48
-rw-r--r--spec/ruby/core/string/split_spec.rb10
-rw-r--r--spec/ruby/core/string/unpack/a_spec.rb3
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb3
-rw-r--r--spec/ruby/core/string/unpack/h_spec.rb3
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb3
-rw-r--r--spec/ruby/core/string/unpack/p_spec.rb43
-rw-r--r--spec/ruby/core/string/unpack/shared/taint.rb81
-rw-r--r--spec/ruby/core/string/unpack/u_spec.rb3
-rw-r--r--spec/ruby/core/string/unpack/z_spec.rb2
-rw-r--r--spec/ruby/core/struct/eql_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/path_spec.rb6
-rw-r--r--spec/ruby/core/time/new_spec.rb16
-rw-r--r--spec/ruby/language/regexp/back-references_spec.rb4
-rw-r--r--spec/ruby/language/regexp_spec.rb27
-rw-r--r--spec/ruby/library/bigdecimal/divmod_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/to_s_spec.rb22
-rw-r--r--spec/ruby/library/datetime/add_spec.rb9
-rw-r--r--spec/ruby/library/datetime/subtract_spec.rb9
-rw-r--r--spec/ruby/library/socket/unixsocket/open_spec.rb2
-rw-r--r--spec/ruby/library/stringio/getbyte_spec.rb6
-rw-r--r--spec/ruby/library/stringio/getc_spec.rb6
-rw-r--r--spec/ruby/library/stringio/getch_spec.rb22
-rw-r--r--spec/ruby/library/stringio/readbyte_spec.rb4
-rw-r--r--spec/ruby/library/stringio/readchar_spec.rb4
-rw-r--r--spec/ruby/library/zlib/crc32_spec.rb2
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb8
-rw-r--r--spec/ruby/optional/capi/object_spec.rb22
-rw-r--r--spec/ruby/security/cve_2018_16396_spec.rb21
-rw-r--r--spec/ruby/shared/basicobject/send.rb7
-rw-r--r--spec/ruby/shared/kernel/raise.rb18
69 files changed, 742 insertions, 141 deletions
diff --git a/spec/ruby/.travis.yml b/spec/ruby/.travis.yml
index dab9d9297c..35fea82656 100644
--- a/spec/ruby/.travis.yml
+++ b/spec/ruby/.travis.yml
@@ -6,15 +6,15 @@ script:
- ../mspec/bin/mspec $MSPEC_OPTS
matrix:
include:
- - rvm: 2.5.1
+ - rvm: 2.5.3
env: MSPEC_OPTS="-R2 -ff"
- - rvm: 2.3.7
- - rvm: 2.4.4
- - rvm: 2.5.1
+ - rvm: 2.3.8
+ - rvm: 2.4.5
+ - rvm: 2.5.3
env: CHECK_LEAKS=true
- rvm: ruby-head
- env: RUBOCOP=true
- rvm: 2.4.4
+ rvm: 2.4.5
script:
- gem install rubocop -v 0.54.0
- rubocop
diff --git a/spec/ruby/core/array/eql_spec.rb b/spec/ruby/core/array/eql_spec.rb
index d4707eb518..8565b94c60 100644
--- a/spec/ruby/core/array/eql_spec.rb
+++ b/spec/ruby/core/array/eql_spec.rb
@@ -6,14 +6,14 @@ describe "Array#eql?" do
it_behaves_like :array_eql, :eql?
it "returns false if any corresponding elements are not #eql?" do
- [1, 2, 3, 4].send(@method, [1, 2, 3, 4.0]).should be_false
+ [1, 2, 3, 4].should_not eql([1, 2, 3, 4.0])
end
it "returns false if other is not a kind of Array" do
obj = mock("array eql?")
obj.should_not_receive(:to_ary)
- obj.should_not_receive(@method)
+ obj.should_not_receive(:eql?)
- [1, 2, 3].send(@method, obj).should be_false
+ [1, 2, 3].should_not eql(obj)
end
end
diff --git a/spec/ruby/core/array/fixtures/classes.rb b/spec/ruby/core/array/fixtures/classes.rb
index 2f8671b29a..7ca9067328 100644
--- a/spec/ruby/core/array/fixtures/classes.rb
+++ b/spec/ruby/core/array/fixtures/classes.rb
@@ -2,9 +2,10 @@ class Object
# This helper is defined here rather than in MSpec because
# it is only used in #pack specs.
def pack_format(count=nil, repeat=nil)
- format = "#{instance_variable_get(:@method)}#{count}"
+ format = instance_variable_get(:@method)
+ format += count.to_s unless format == 'P' || format == 'p'
format *= repeat if repeat
- format
+ format.dup # because it may then become tainted
end
end
diff --git a/spec/ruby/core/array/pack/a_spec.rb b/spec/ruby/core/array/pack/a_spec.rb
index 223e99cefe..1cee3858ff 100644
--- a/spec/ruby/core/array/pack/a_spec.rb
+++ b/spec/ruby/core/array/pack/a_spec.rb
@@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
+require_relative 'shared/taint'
describe "Array#pack with format 'A'" do
it_behaves_like :array_pack_basic, 'A'
it_behaves_like :array_pack_basic_non_float, 'A'
it_behaves_like :array_pack_no_platform, 'A'
it_behaves_like :array_pack_string, 'A'
+ it_behaves_like :array_pack_taint, 'A'
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("A*").should == "abc"
@@ -36,6 +38,7 @@ describe "Array#pack with format 'a'" do
it_behaves_like :array_pack_basic_non_float, 'a'
it_behaves_like :array_pack_no_platform, 'a'
it_behaves_like :array_pack_string, 'a'
+ it_behaves_like :array_pack_taint, 'a'
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("a*").should == "abc"
diff --git a/spec/ruby/core/array/pack/b_spec.rb b/spec/ruby/core/array/pack/b_spec.rb
index 2756a6bfb1..8a75825e3e 100644
--- a/spec/ruby/core/array/pack/b_spec.rb
+++ b/spec/ruby/core/array/pack/b_spec.rb
@@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/encodings'
+require_relative 'shared/taint'
describe "Array#pack with format 'B'" do
it_behaves_like :array_pack_basic, 'B'
it_behaves_like :array_pack_basic_non_float, 'B'
it_behaves_like :array_pack_arguments, 'B'
it_behaves_like :array_pack_hex, 'B'
+ it_behaves_like :array_pack_taint, 'B'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
@@ -59,6 +61,7 @@ describe "Array#pack with format 'b'" do
it_behaves_like :array_pack_basic_non_float, 'b'
it_behaves_like :array_pack_arguments, 'b'
it_behaves_like :array_pack_hex, 'b'
+ it_behaves_like :array_pack_taint, 'b'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
diff --git a/spec/ruby/core/array/pack/h_spec.rb b/spec/ruby/core/array/pack/h_spec.rb
index fee2d1efec..51bf551ba3 100644
--- a/spec/ruby/core/array/pack/h_spec.rb
+++ b/spec/ruby/core/array/pack/h_spec.rb
@@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/encodings'
+require_relative 'shared/taint'
describe "Array#pack with format 'H'" do
it_behaves_like :array_pack_basic, 'H'
it_behaves_like :array_pack_basic_non_float, 'H'
it_behaves_like :array_pack_arguments, 'H'
it_behaves_like :array_pack_hex, 'H'
+ it_behaves_like :array_pack_taint, 'H'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
@@ -105,6 +107,7 @@ describe "Array#pack with format 'h'" do
it_behaves_like :array_pack_basic_non_float, 'h'
it_behaves_like :array_pack_arguments, 'h'
it_behaves_like :array_pack_hex, 'h'
+ it_behaves_like :array_pack_taint, 'h'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
diff --git a/spec/ruby/core/array/pack/m_spec.rb b/spec/ruby/core/array/pack/m_spec.rb
index a29f1937e8..24acf2cef2 100644
--- a/spec/ruby/core/array/pack/m_spec.rb
+++ b/spec/ruby/core/array/pack/m_spec.rb
@@ -2,11 +2,13 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
+require_relative 'shared/taint'
describe "Array#pack with format 'M'" do
it_behaves_like :array_pack_basic, 'M'
it_behaves_like :array_pack_basic_non_float, 'M'
it_behaves_like :array_pack_arguments, 'M'
+ it_behaves_like :array_pack_taint, 'M'
it "encodes an empty string as an empty string" do
[""].pack("M").should == ""
@@ -192,6 +194,7 @@ describe "Array#pack with format 'm'" do
it_behaves_like :array_pack_basic, 'm'
it_behaves_like :array_pack_basic_non_float, 'm'
it_behaves_like :array_pack_arguments, 'm'
+ it_behaves_like :array_pack_taint, 'm'
it "encodes an empty string as an empty string" do
[""].pack("m").should == ""
diff --git a/spec/ruby/core/array/pack/p_spec.rb b/spec/ruby/core/array/pack/p_spec.rb
index d562108967..857d403313 100644
--- a/spec/ruby/core/array/pack/p_spec.rb
+++ b/spec/ruby/core/array/pack/p_spec.rb
@@ -1,11 +1,58 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
+require_relative 'shared/taint'
describe "Array#pack with format 'P'" do
it_behaves_like :array_pack_basic_non_float, 'P'
+ it_behaves_like :array_pack_taint, 'P'
+
+ it "produces as many bytes as there are in a pointer" do
+ ["hello"].pack("P").size.should == [0].pack("J").size
+ end
+
+ it "round-trips a string through pack and unpack" do
+ ["hello"].pack("P").unpack("P5").should == ["hello"]
+ end
+
+ it "taints the input string" do
+ input_string = "hello"
+ [input_string].pack("P")
+ input_string.tainted?.should be_true
+ end
+
+ it "does not taint the output string in normal cases" do
+ ["hello"].pack("P").tainted?.should be_false
+ end
+
+ it "with nil gives a null pointer" do
+ [nil].pack("P").unpack("J").should == [0]
+ end
end
describe "Array#pack with format 'p'" do
it_behaves_like :array_pack_basic_non_float, 'p'
+ it_behaves_like :array_pack_taint, 'p'
+
+ it "produces as many bytes as there are in a pointer" do
+ ["hello"].pack("p").size.should == [0].pack("J").size
+ end
+
+ it "round-trips a string through pack and unpack" do
+ ["hello"].pack("p").unpack("p").should == ["hello"]
+ end
+
+ it "taints the input string" do
+ input_string = "hello"
+ [input_string].pack("p")
+ input_string.tainted?.should be_true
+ end
+
+ it "does not taint the output string in normal cases" do
+ ["hello"].pack("p").tainted?.should be_false
+ end
+
+ it "with nil gives a null pointer" do
+ [nil].pack("p").unpack("J").should == [0]
+ end
end
diff --git a/spec/ruby/core/array/pack/shared/string.rb b/spec/ruby/core/array/pack/shared/string.rb
index cedb0886e2..256c1c08e8 100644
--- a/spec/ruby/core/array/pack/shared/string.rb
+++ b/spec/ruby/core/array/pack/shared/string.rb
@@ -36,38 +36,6 @@ describe :array_pack_string, shared: true do
lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
end
- it "returns a tainted string when a pack argument is tainted" do
- ["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true
- end
-
- it "does not return a tainted string when the array is tainted" do
- ["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false
- end
-
- it "returns a tainted string when the format is tainted" do
- ["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true
- end
-
- it "returns a tainted string when an empty format is tainted" do
- ["abcd", 0x20].pack("".taint).tainted?.should be_true
- end
-
- it "returns a untrusted string when the format is untrusted" do
- ["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true
- end
-
- it "returns a untrusted string when the empty format is untrusted" do
- ["abcd", 0x20].pack("".untrust).untrusted?.should be_true
- end
-
- it "returns a untrusted string when a pack argument is untrusted" do
- ["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true
- end
-
- it "returns a trusted string when the array is untrusted" do
- ["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false
- end
-
it "returns a string in encoding of common to the concatenated results" do
f = pack_format("*")
[ [["\u{3042 3044 3046 3048}", 0x2000B].pack(f+"U"), Encoding::ASCII_8BIT],
diff --git a/spec/ruby/core/array/pack/shared/taint.rb b/spec/ruby/core/array/pack/shared/taint.rb
new file mode 100644
index 0000000000..88f349cb24
--- /dev/null
+++ b/spec/ruby/core/array/pack/shared/taint.rb
@@ -0,0 +1,33 @@
+describe :array_pack_taint, shared: true do
+ it "returns a tainted string when a pack argument is tainted" do
+ ["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true
+ end
+
+ it "does not return a tainted string when the array is tainted" do
+ ["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false
+ end
+
+ it "returns a tainted string when the format is tainted" do
+ ["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true
+ end
+
+ it "returns a tainted string when an empty format is tainted" do
+ ["abcd", 0x20].pack("".taint).tainted?.should be_true
+ end
+
+ it "returns a untrusted string when the format is untrusted" do
+ ["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true
+ end
+
+ it "returns a untrusted string when the empty format is untrusted" do
+ ["abcd", 0x20].pack("".untrust).untrusted?.should be_true
+ end
+
+ it "returns a untrusted string when a pack argument is untrusted" do
+ ["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true
+ end
+
+ it "returns a trusted string when the array is untrusted" do
+ ["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false
+ end
+end
diff --git a/spec/ruby/core/array/pack/u_spec.rb b/spec/ruby/core/array/pack/u_spec.rb
index 9c248165b3..d708518c16 100644
--- a/spec/ruby/core/array/pack/u_spec.rb
+++ b/spec/ruby/core/array/pack/u_spec.rb
@@ -3,6 +3,7 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/unicode'
+require_relative 'shared/taint'
describe "Array#pack with format 'U'" do
it_behaves_like :array_pack_basic, 'U'
@@ -15,6 +16,7 @@ describe "Array#pack with format 'u'" do
it_behaves_like :array_pack_basic, 'u'
it_behaves_like :array_pack_basic_non_float, 'u'
it_behaves_like :array_pack_arguments, 'u'
+ it_behaves_like :array_pack_taint, 'u'
it "encodes an empty string as an empty string" do
[""].pack("u").should == ""
diff --git a/spec/ruby/core/array/pack/z_spec.rb b/spec/ruby/core/array/pack/z_spec.rb
index 8c89aa9d2a..d0600f0c26 100644
--- a/spec/ruby/core/array/pack/z_spec.rb
+++ b/spec/ruby/core/array/pack/z_spec.rb
@@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
+require_relative 'shared/taint'
describe "Array#pack with format 'Z'" do
it_behaves_like :array_pack_basic, 'Z'
it_behaves_like :array_pack_basic_non_float, 'Z'
it_behaves_like :array_pack_no_platform, 'Z'
it_behaves_like :array_pack_string, 'Z'
+ it_behaves_like :array_pack_taint, 'Z'
it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do
["abc"].pack("Z*").should == "abc\x00"
diff --git a/spec/ruby/core/enumerable/all_spec.rb b/spec/ruby/core/enumerable/all_spec.rb
index bd87a361d4..b02ac8b21b 100644
--- a/spec/ruby/core/enumerable/all_spec.rb
+++ b/spec/ruby/core/enumerable/all_spec.rb
@@ -68,7 +68,6 @@ describe "Enumerable#all?" do
end
it "gathers whole arrays as elements when each yields multiple" do
- # This spec doesn't spec what it says it does
multi = EnumerableSpecs::YieldsMultiWithFalse.new
multi.all?.should be_true
end
diff --git a/spec/ruby/core/enumerable/none_spec.rb b/spec/ruby/core/enumerable/none_spec.rb
index 99fbb24a95..bff252df5e 100644
--- a/spec/ruby/core/enumerable/none_spec.rb
+++ b/spec/ruby/core/enumerable/none_spec.rb
@@ -51,7 +51,6 @@ describe "Enumerable#none?" do
end
it "gathers whole arrays as elements when each yields multiple" do
- # This spec doesn't spec what it says it does
multi = EnumerableSpecs::YieldsMultiWithFalse.new
multi.none?.should be_false
end
diff --git a/spec/ruby/core/enumerable/one_spec.rb b/spec/ruby/core/enumerable/one_spec.rb
index d3ff42890f..2bd67adc26 100644
--- a/spec/ruby/core/enumerable/one_spec.rb
+++ b/spec/ruby/core/enumerable/one_spec.rb
@@ -78,7 +78,6 @@ describe "Enumerable#one?" do
end
it "gathers initial args as elements when each yields multiple" do
- # This spec doesn't spec what it says it does
multi = EnumerableSpecs::YieldsMulti.new
yielded = []
multi.one? { |e| yielded << e; false }.should == false
diff --git a/spec/ruby/core/hash/slice_spec.rb b/spec/ruby/core/hash/slice_spec.rb
index d414b1919f..f7717c9404 100644
--- a/spec/ruby/core/hash/slice_spec.rb
+++ b/spec/ruby/core/hash/slice_spec.rb
@@ -6,10 +6,11 @@ ruby_version_is "2.5" do
@hash = { a: 1, b: 2, c: 3 }
end
- it "returns new hash" do
+ it "returns a new empty hash without arguments" do
ret = @hash.slice
ret.should_not equal(@hash)
ret.should be_an_instance_of(Hash)
+ ret.should == {}
end
it "returns the requested subset" do
@@ -27,10 +28,28 @@ ruby_version_is "2.5" do
it "returns a Hash instance, even on subclasses" do
klass = Class.new(Hash)
h = klass.new
+ h[:bar] = 12
h[:foo] = 42
r = h.slice(:foo)
r.should == {foo: 42}
r.class.should == Hash
end
+
+ it "uses the regular Hash#[] method, even on subclasses that override it" do
+ ScratchPad.record []
+ klass = Class.new(Hash) do
+ def [](value)
+ ScratchPad << :used_subclassed_operator
+ super
+ end
+ end
+
+ h = klass.new
+ h[:bar] = 12
+ h[:foo] = 42
+ h.slice(:foo)
+
+ ScratchPad.recorded.should == []
+ end
end
end
diff --git a/spec/ruby/core/io/pread_spec.rb b/spec/ruby/core/io/pread_spec.rb
new file mode 100644
index 0000000000..b5b516fa53
--- /dev/null
+++ b/spec/ruby/core/io/pread_spec.rb
@@ -0,0 +1,52 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+
+ruby_version_is "2.5" do
+ platform_is_not :windows do
+ describe "IO#pread" do
+ before :each do
+ @fname = tmp("io_pread.txt")
+ @contents = "1234567890"
+ touch(@fname) { |f| f.write @contents }
+ @file = File.open(@fname, "r+")
+ end
+
+ after :each do
+ @file.close
+ rm_r @fname
+ end
+
+ it "accepts a length, and an offset" do
+ @file.pread(4, 0).should == "1234"
+ @file.pread(3, 4).should == "567"
+ end
+
+ it "accepts a length, an offset, and an output buffer" do
+ buffer = "foo"
+ @file.pread(3, 4, buffer)
+ buffer.should == "567"
+ end
+
+ it "does not advance the file pointer" do
+ @file.pread(4, 0).should == "1234"
+ @file.read.should == "1234567890"
+ end
+
+ it "raises EOFError if end-of-file is reached" do
+ lambda { @file.pread(1, 10) }.should raise_error(EOFError)
+ end
+
+ it "raises IOError when file is not open in read mode" do
+ File.open(@fname, "w") do |file|
+ lambda { file.pread(1, 1) }.should raise_error(IOError)
+ end
+ end
+
+ it "raises IOError when file is closed" do
+ file = File.open(@fname, "r+")
+ file.close
+ lambda { file.pread(1, 1) }.should raise_error(IOError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/pwrite_spec.rb b/spec/ruby/core/io/pwrite_spec.rb
new file mode 100644
index 0000000000..fd3d1b98e9
--- /dev/null
+++ b/spec/ruby/core/io/pwrite_spec.rb
@@ -0,0 +1,45 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+
+ruby_version_is "2.5" do
+ platform_is_not :windows do
+ describe "IO#pwrite" do
+ before :each do
+ @fname = tmp("io_pwrite.txt")
+ @file = File.open(@fname, "w+")
+ end
+
+ after :each do
+ @file.close
+ rm_r @fname
+ end
+
+ it "returns the number of bytes written" do
+ @file.pwrite("foo", 0).should == 3
+ end
+
+ it "accepts a string and an offset" do
+ @file.pwrite("foo", 2)
+ @file.pread(3, 2).should == "foo"
+ end
+
+ it "does not advance the pointer in the file" do
+ @file.pwrite("bar", 3)
+ @file.write("foo")
+ @file.pread(6, 0).should == "foobar"
+ end
+
+ it "raises IOError when file is not open in write mode" do
+ File.open(@fname, "r") do |file|
+ lambda { file.pwrite("foo", 1) }.should raise_error(IOError)
+ end
+ end
+
+ it "raises IOError when file is closed" do
+ file = File.open(@fname, "w+")
+ file.close
+ lambda { file.pwrite("foo", 1) }.should raise_error(IOError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb
index e6db3351db..50e3df864d 100644
--- a/spec/ruby/core/io/write_spec.rb
+++ b/spec/ruby/core/io/write_spec.rb
@@ -127,6 +127,17 @@ end
describe "IO#write" do
it_behaves_like :io_write, :write
+
+ ruby_version_is "2.5" do
+ it "accepts multiple arguments" do
+ IO.pipe do |r, w|
+ w.write("foo", "bar")
+ w.close
+
+ r.read.should == "foobar"
+ end
+ end
+ end
end
platform_is :windows do
diff --git a/spec/ruby/core/kernel/Complex_spec.rb b/spec/ruby/core/kernel/Complex_spec.rb
index f738f43a10..44e4f44ada 100644
--- a/spec/ruby/core/kernel/Complex_spec.rb
+++ b/spec/ruby/core/kernel/Complex_spec.rb
@@ -126,8 +126,8 @@ describe "Kernel.Complex()" do
describe "when passed a non-Numeric second argument" do
it "raises TypeError" do
- lambda { Complex.send(@method, :sym, :sym) }.should raise_error(TypeError)
- lambda { Complex.send(@method, 0, :sym) }.should raise_error(TypeError)
+ lambda { Complex(:sym, :sym) }.should raise_error(TypeError)
+ lambda { Complex(0, :sym) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/kernel/fixtures/classes.rb b/spec/ruby/core/kernel/fixtures/classes.rb
index cc475ed758..1f45bbb083 100644
--- a/spec/ruby/core/kernel/fixtures/classes.rb
+++ b/spec/ruby/core/kernel/fixtures/classes.rb
@@ -68,6 +68,7 @@ module KernelSpecs
module SomeOtherModule; end
module AncestorModule; end
module MyModule; end
+ module MyPrependedModule; end
module MyExtensionModule; end
class AncestorClass < String
@@ -80,6 +81,8 @@ module KernelSpecs
class KindaClass < AncestorClass
include MyModule
+ prepend MyPrependedModule
+
def initialize
self.extend MyExtensionModule
end
diff --git a/spec/ruby/core/kernel/shared/kind_of.rb b/spec/ruby/core/kernel/shared/kind_of.rb
index 690018d655..0614c02214 100644
--- a/spec/ruby/core/kernel/shared/kind_of.rb
+++ b/spec/ruby/core/kernel/shared/kind_of.rb
@@ -31,7 +31,11 @@ describe :kernel_kind_of, shared: true do
@o.send(@method, KernelSpecs::MyExtensionModule).should == true
end
- it "returns false if given a Module not included in object's class nor ancestors" do
+ it "returns true if given a Module that object has been prepended with" do
+ @o.send(@method, KernelSpecs::MyPrependedModule).should == true
+ end
+
+ it "returns false if given a Module not included nor prepended in object's class nor ancestors" do
@o.send(@method, KernelSpecs::SomeOtherModule).should == false
end
@@ -41,4 +45,11 @@ describe :kernel_kind_of, shared: true do
lambda { @o.send(@method, :KindaClass) }.should raise_error(TypeError)
lambda { @o.send(@method, Object.new) }.should raise_error(TypeError)
end
+
+ it "does not take into account `class` method overriding" do
+ def @o.class; Integer; end
+
+ @o.send(@method, Integer).should == false
+ @o.send(@method, KernelSpecs::KindaClass).should == true
+ end
end
diff --git a/spec/ruby/core/proc/element_reference_spec.rb b/spec/ruby/core/proc/element_reference_spec.rb
index 1c9b89521a..f60ae1b086 100644
--- a/spec/ruby/core/proc/element_reference_spec.rb
+++ b/spec/ruby/core/proc/element_reference_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/call'
require_relative 'shared/call_arguments'
+require_relative 'fixtures/proc_aref'
+require_relative 'fixtures/proc_aref_frozen'
describe "Proc#[]" do
it_behaves_like :proc_call, :[]
@@ -14,3 +16,14 @@ end
describe "Proc#call on a Proc created with Kernel#lambda or Kernel#proc" do
it_behaves_like :proc_call_on_proc_or_lambda, :call
end
+
+ruby_bug "#15118", ""..."2.6" do
+ describe "Proc#[] with frozen_string_literals" do
+ it "doesn't duplicate frozen strings" do
+ ProcArefSpecs.aref.frozen?.should be_false
+ ProcArefSpecs.aref_freeze.frozen?.should be_true
+ ProcArefFrozenSpecs.aref.frozen?.should be_true
+ ProcArefFrozenSpecs.aref_freeze.frozen?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/core/proc/fixtures/proc_aref.rb b/spec/ruby/core/proc/fixtures/proc_aref.rb
new file mode 100644
index 0000000000..a305667797
--- /dev/null
+++ b/spec/ruby/core/proc/fixtures/proc_aref.rb
@@ -0,0 +1,9 @@
+module ProcArefSpecs
+ def self.aref
+ proc {|a| a }["sometext"]
+ end
+
+ def self.aref_freeze
+ proc {|a| a }["sometext".freeze]
+ end
+end
diff --git a/spec/ruby/core/proc/fixtures/proc_aref_frozen.rb b/spec/ruby/core/proc/fixtures/proc_aref_frozen.rb
new file mode 100644
index 0000000000..50a330ba4f
--- /dev/null
+++ b/spec/ruby/core/proc/fixtures/proc_aref_frozen.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+module ProcArefFrozenSpecs
+ def self.aref
+ proc {|a| a }["sometext"]
+ end
+
+ def self.aref_freeze
+ proc {|a| a }["sometext".freeze]
+ end
+end
diff --git a/spec/ruby/core/proc/shared/to_s.rb b/spec/ruby/core/proc/shared/to_s.rb
index c3f82a73f3..530eaff3a0 100644
--- a/spec/ruby/core/proc/shared/to_s.rb
+++ b/spec/ruby/core/proc/shared/to_s.rb
@@ -3,18 +3,30 @@ describe :proc_to_s, shared: true do
it "returns a description optionally including file and line number" do
Proc.new { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:4)?>$/
end
+
+ it "has an ASCII-8BIT encoding" do
+ Proc.new { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT
+ end
end
describe "for a proc created with lambda" do
it "returns a description including '(lambda)' and optionally including file and line number" do
lambda { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:10)? \(lambda\)>$/
end
+
+ it "has an ASCII-8BIT encoding" do
+ lambda { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT
+ end
end
describe "for a proc created with proc" do
it "returns a description optionally including file and line number" do
proc { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:16)?>$/
end
+
+ it "has an ASCII-8BIT encoding" do
+ proc { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT
+ end
end
describe "for a proc created with UnboundMethod#to_proc" do
@@ -23,5 +35,11 @@ describe :proc_to_s, shared: true do
method("hello").to_proc.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:22)? \(lambda\)>$/
end
+
+ it "has an ASCII-8BIT encoding" do
+ def hello; end
+
+ method("hello").to_proc.send(@method).encoding.should == Encoding::ASCII_8BIT
+ end
end
end
diff --git a/spec/ruby/core/random/bytes_spec.rb b/spec/ruby/core/random/bytes_spec.rb
index 7fe62c334b..2caf18fbd0 100644
--- a/spec/ruby/core/random/bytes_spec.rb
+++ b/spec/ruby/core/random/bytes_spec.rb
@@ -1,18 +1,9 @@
# -*- encoding: binary -*-
require_relative '../../spec_helper'
+require_relative 'shared/bytes'
describe "Random#bytes" do
- it "returns a String" do
- Random.new.bytes(1).should be_an_instance_of(String)
- end
-
- it "returns a String of the length given as argument" do
- Random.new.bytes(15).length.should == 15
- end
-
- it "returns an ASCII-8BIT String" do
- Random.new.bytes(15).encoding.should == Encoding::ASCII_8BIT
- end
+ it_behaves_like :random_bytes, :bytes, Random.new
it "returns the same output for a given seed" do
Random.new(33).bytes(2).should == Random.new(33).bytes(2)
@@ -32,8 +23,10 @@ describe "Random#bytes" do
rnd.bytes(1000) # skip some
rnd.bytes(2).should == "\x17\x12"
end
+end
- it "returns a random binary String" do
- Random.new.bytes(12).should_not == Random.new.bytes(12)
+ruby_version_is "2.6" do
+ describe "Random.bytes" do
+ it_behaves_like :random_bytes, :bytes, Random
end
end
diff --git a/spec/ruby/core/random/shared/bytes.rb b/spec/ruby/core/random/shared/bytes.rb
new file mode 100644
index 0000000000..3485d0f221
--- /dev/null
+++ b/spec/ruby/core/random/shared/bytes.rb
@@ -0,0 +1,17 @@
+describe :random_bytes, shared: true do
+ it "returns a String" do
+ @object.bytes(1).should be_an_instance_of(String)
+ end
+
+ it "returns a String of the length given as argument" do
+ @object.bytes(15).length.should == 15
+ end
+
+ it "returns an ASCII-8BIT String" do
+ @object.bytes(15).encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns a random binary String" do
+ @object.bytes(12).should_not == @object.bytes(12)
+ end
+end
diff --git a/spec/ruby/core/range/eql_spec.rb b/spec/ruby/core/range/eql_spec.rb
index c62fa0076e..fa6c71840e 100644
--- a/spec/ruby/core/range/eql_spec.rb
+++ b/spec/ruby/core/range/eql_spec.rb
@@ -5,6 +5,6 @@ describe "Range#eql?" do
it_behaves_like :range_eql, :eql?
it "returns false if the endpoints are not eql?" do
- (0..1).send(@method, 0..1.0).should == false
+ (0..1).should_not eql(0..1.0)
end
end
diff --git a/spec/ruby/core/range/equal_value_spec.rb b/spec/ruby/core/range/equal_value_spec.rb
index baa5d0d411..889557fc2a 100644
--- a/spec/ruby/core/range/equal_value_spec.rb
+++ b/spec/ruby/core/range/equal_value_spec.rb
@@ -5,6 +5,6 @@ describe "Range#==" do
it_behaves_like :range_eql, :==
it "returns true if the endpoints are ==" do
- (0..1).send(@method, 0..1.0).should == true
+ (0..1).should == (0..1.0)
end
end
diff --git a/spec/ruby/core/string/chars_spec.rb b/spec/ruby/core/string/chars_spec.rb
index 54876f9f9d..e4f26bc0cc 100644
--- a/spec/ruby/core/string/chars_spec.rb
+++ b/spec/ruby/core/string/chars_spec.rb
@@ -5,7 +5,6 @@ describe "String#chars" do
it_behaves_like :string_chars, :chars
it "returns an array when no block given" do
- ary = "hello".send(@method)
- ary.should == ['h', 'e', 'l', 'l', 'o']
+ "hello".chars.should == ['h', 'e', 'l', 'l', 'o']
end
end
diff --git a/spec/ruby/core/string/codepoints_spec.rb b/spec/ruby/core/string/codepoints_spec.rb
index 66f2884168..bccb3d0484 100644
--- a/spec/ruby/core/string/codepoints_spec.rb
+++ b/spec/ruby/core/string/codepoints_spec.rb
@@ -8,13 +8,13 @@ with_feature :encoding do
it_behaves_like :string_codepoints, :codepoints
it "returns an Array when no block is given" do
- "abc".send(@method).should == [?a.ord, ?b.ord, ?c.ord]
+ "abc".codepoints.should == [?a.ord, ?b.ord, ?c.ord]
end
it "raises an ArgumentError when no block is given if self has an invalid encoding" do
s = "\xDF".force_encoding(Encoding::UTF_8)
s.valid_encoding?.should be_false
- lambda {s.send(@method)}.should raise_error(ArgumentError)
+ lambda { s.codepoints }.should raise_error(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/string/each_grapheme_cluster_spec.rb b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
new file mode 100644
index 0000000000..5367f84887
--- /dev/null
+++ b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
@@ -0,0 +1,11 @@
+require_relative 'shared/chars'
+require_relative 'shared/grapheme_clusters'
+require_relative 'shared/each_char_without_block'
+
+ruby_version_is "2.5" do
+ describe "String#each_grapheme_cluster" do
+ it_behaves_like :string_chars, :each_grapheme_cluster
+ it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster
+ it_behaves_like :string_each_char_without_block, :each_grapheme_cluster
+ end
+end
diff --git a/spec/ruby/core/string/fixtures/classes.rb b/spec/ruby/core/string/fixtures/classes.rb
index 6af106f9d3..1cc7600abb 100644
--- a/spec/ruby/core/string/fixtures/classes.rb
+++ b/spec/ruby/core/string/fixtures/classes.rb
@@ -4,7 +4,7 @@ class Object
def unpack_format(count=nil, repeat=nil)
format = "#{instance_variable_get(:@method)}#{count}"
format *= repeat if repeat
- format
+ format.dup # because it may then become tainted
end
end
diff --git a/spec/ruby/core/string/grapheme_clusters_spec.rb b/spec/ruby/core/string/grapheme_clusters_spec.rb
new file mode 100644
index 0000000000..0cba0e4216
--- /dev/null
+++ b/spec/ruby/core/string/grapheme_clusters_spec.rb
@@ -0,0 +1,15 @@
+require_relative 'shared/chars'
+require_relative 'shared/grapheme_clusters'
+
+ruby_version_is "2.5" do
+ describe "String#grapheme_clusters" do
+ it_behaves_like :string_chars, :grapheme_clusters
+ it_behaves_like :string_grapheme_clusters, :grapheme_clusters
+
+ it "returns an array when no block given" do
+ string = "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}"
+ string.grapheme_clusters.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"]
+
+ end
+ end
+end
diff --git a/spec/ruby/core/string/lines_spec.rb b/spec/ruby/core/string/lines_spec.rb
index 6b2d74daf1..1c13936c30 100644
--- a/spec/ruby/core/string/lines_spec.rb
+++ b/spec/ruby/core/string/lines_spec.rb
@@ -7,7 +7,7 @@ describe "String#lines" do
it_behaves_like :string_each_line, :lines
it "returns an array when no block given" do
- ary = "hello world".send(@method, ' ')
+ ary = "hello world".lines(' ')
ary.should == ["hello ", "world"]
end
diff --git a/spec/ruby/core/string/modulo_spec.rb b/spec/ruby/core/string/modulo_spec.rb
index e81b27e4ce..72738ece24 100644
--- a/spec/ruby/core/string/modulo_spec.rb
+++ b/spec/ruby/core/string/modulo_spec.rb
@@ -19,6 +19,23 @@ describe "String#%" do
("%d%% %s" % [10, "of chickens!"]).should == "10% of chickens!"
end
+ describe "output's encoding" do
+ it "is the same as the format string if passed value is encoding-compatible" do
+ [Encoding::ASCII_8BIT, Encoding::US_ASCII, Encoding::UTF_8, Encoding::SHIFT_JIS].each do |encoding|
+ ("hello %s!".encode(encoding) % "world").encoding.should == encoding
+ end
+ end
+
+ it "negotiates a compatible encoding if necessary" do
+ ("hello %s" % 195.chr).encoding.should == Encoding::ASCII_8BIT
+ ("hello %s".encode("shift_jis") % "wörld").encoding.should == Encoding::UTF_8
+ end
+
+ it "raises if a compatible encoding can't be found" do
+ lambda { "hello %s".encode("utf-8") % "world".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError)
+ end
+ end
+
ruby_version_is ""..."2.5" do
it "formats single % character at the end as literal %" do
("%" % []).should == "%"
diff --git a/spec/ruby/core/string/shared/grapheme_clusters.rb b/spec/ruby/core/string/shared/grapheme_clusters.rb
new file mode 100644
index 0000000000..8b666868b1
--- /dev/null
+++ b/spec/ruby/core/string/shared/grapheme_clusters.rb
@@ -0,0 +1,16 @@
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+
+describe :string_grapheme_clusters, shared: true do
+ it "passes each grapheme cluster in self to the given block" do
+ a = []
+ # test string: abc[rainbow flag emoji][paw prints]
+ "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}".send(@method) { |c| a << c }
+ a.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"]
+ end
+
+ it "returns self" do
+ s = StringSpecs::MyString.new "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}"
+ s.send(@method) {}.should equal(s)
+ end
+end
diff --git a/spec/ruby/core/string/slice_spec.rb b/spec/ruby/core/string/slice_spec.rb
index 12876e757d..a3e9d6b74f 100644
--- a/spec/ruby/core/string/slice_spec.rb
+++ b/spec/ruby/core/string/slice_spec.rb
@@ -75,9 +75,9 @@ describe "String#slice! with index" do
with_feature :encoding do
it "returns the character given by the character index" do
- "hellö there".send(@method, 1).should == "e"
- "hellö there".send(@method, 4).should == "ö"
- "hellö there".send(@method, 6).should == "t"
+ "hellö there".slice!(1).should == "e"
+ "hellö there".slice!(4).should == "ö"
+ "hellö there".slice!(6).should == "t"
end
end
@@ -151,15 +151,15 @@ describe "String#slice! with index, length" do
with_feature :encoding do
it "returns the substring given by the character offsets" do
- "hellö there".send(@method, 1,0).should == ""
- "hellö there".send(@method, 1,3).should == "ell"
- "hellö there".send(@method, 1,6).should == "ellö t"
- "hellö there".send(@method, 1,9).should == "ellö ther"
+ "hellö there".slice!(1,0).should == ""
+ "hellö there".slice!(1,3).should == "ell"
+ "hellö there".slice!(1,6).should == "ellö t"
+ "hellö there".slice!(1,9).should == "ellö ther"
end
it "treats invalid bytes as single bytes" do
xE6xCB = [0xE6,0xCB].pack('CC').force_encoding('utf-8')
- "a#{xE6xCB}b".send(@method, 1, 2).should == xE6xCB
+ "a#{xE6xCB}b".slice!(1, 2).should == xE6xCB
end
end
end
@@ -239,13 +239,13 @@ describe "String#slice! Range" do
with_feature :encoding do
it "returns the substring given by the character offsets of the range" do
- "hellö there".send(@method, 1..1).should == "e"
- "hellö there".send(@method, 1..3).should == "ell"
- "hellö there".send(@method, 1...3).should == "el"
- "hellö there".send(@method, -4..-2).should == "her"
- "hellö there".send(@method, -4...-2).should == "he"
- "hellö there".send(@method, 5..-1).should == " there"
- "hellö there".send(@method, 5...-1).should == " ther"
+ "hellö there".slice!(1..1).should == "e"
+ "hellö there".slice!(1..3).should == "ell"
+ "hellö there".slice!(1...3).should == "el"
+ "hellö there".slice!(-4..-2).should == "her"
+ "hellö there".slice!(-4...-2).should == "he"
+ "hellö there".slice!(5..-1).should == " there"
+ "hellö there".slice!(5...-1).should == " ther"
end
end
@@ -307,8 +307,8 @@ describe "String#slice! with Regexp" do
with_feature :encoding do
it "returns the matching portion of self with a multi byte character" do
- "hëllo there".send(@method, /[ë](.)\1/).should == "ëll"
- "".send(@method, //).should == ""
+ "hëllo there".slice!(/[ë](.)\1/).should == "ëll"
+ "".slice!(//).should == ""
end
end
@@ -391,13 +391,13 @@ describe "String#slice! with Regexp, index" do
with_feature :encoding do
it "returns the encoding aware capture for the given index" do
- "hår".send(@method, /(.)(.)(.)/, 0).should == "hår"
- "hår".send(@method, /(.)(.)(.)/, 1).should == "h"
- "hår".send(@method, /(.)(.)(.)/, 2).should == "å"
- "hår".send(@method, /(.)(.)(.)/, 3).should == "r"
- "hår".send(@method, /(.)(.)(.)/, -1).should == "r"
- "hår".send(@method, /(.)(.)(.)/, -2).should == "å"
- "hår".send(@method, /(.)(.)(.)/, -3).should == "h"
+ "hår".slice!(/(.)(.)(.)/, 0).should == "hår"
+ "hår".slice!(/(.)(.)(.)/, 1).should == "h"
+ "hår".slice!(/(.)(.)(.)/, 2).should == "å"
+ "hår".slice!(/(.)(.)(.)/, 3).should == "r"
+ "hår".slice!(/(.)(.)(.)/, -1).should == "r"
+ "hår".slice!(/(.)(.)(.)/, -2).should == "å"
+ "hår".slice!(/(.)(.)(.)/, -3).should == "h"
end
end
diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb
index 0d2c6211c4..b89a28c149 100644
--- a/spec/ruby/core/string/split_spec.rb
+++ b/spec/ruby/core/string/split_spec.rb
@@ -402,4 +402,14 @@ describe "String#split with Regexp" do
broken_str.force_encoding('utf-8')
lambda{ broken_str.split(/\r\n|\r|\n/) }.should raise_error(ArgumentError)
end
+
+ ruby_version_is "2.6" do
+ it "yields each split substrings if a block is given" do
+ a = []
+ returned_object = "chunky bacon".split(" ") { |str| a << str.capitalize }
+
+ returned_object.should == "chunky bacon"
+ a.should == ["Chunky", "Bacon"]
+ end
+ end
end
diff --git a/spec/ruby/core/string/unpack/a_spec.rb b/spec/ruby/core/string/unpack/a_spec.rb
index 0adcf0ff80..3de338e2e1 100644
--- a/spec/ruby/core/string/unpack/a_spec.rb
+++ b/spec/ruby/core/string/unpack/a_spec.rb
@@ -3,12 +3,14 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
+require_relative 'shared/taint'
describe "String#unpack with format 'A'" do
it_behaves_like :string_unpack_basic, 'A'
it_behaves_like :string_unpack_no_platform, 'A'
it_behaves_like :string_unpack_string, 'A'
it_behaves_like :string_unpack_Aa, 'A'
+ it_behaves_like :string_unpack_taint, 'A'
it "removes trailing space and NULL bytes from the decoded string" do
[ ["a\x00 b \x00", ["a\x00 b", ""]],
@@ -40,6 +42,7 @@ describe "String#unpack with format 'a'" do
it_behaves_like :string_unpack_no_platform, 'a'
it_behaves_like :string_unpack_string, 'a'
it_behaves_like :string_unpack_Aa, 'a'
+ it_behaves_like :string_unpack_taint, 'a'
it "does not remove trailing whitespace or NULL bytes from the decoded string" do
[ ["a\x00 b \x00", ["a\x00 b \x00"]],
diff --git a/spec/ruby/core/string/unpack/b_spec.rb b/spec/ruby/core/string/unpack/b_spec.rb
index 332c85b5f8..a0bbc3d421 100644
--- a/spec/ruby/core/string/unpack/b_spec.rb
+++ b/spec/ruby/core/string/unpack/b_spec.rb
@@ -2,10 +2,12 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
+require_relative 'shared/taint'
describe "String#unpack with format 'B'" do
it_behaves_like :string_unpack_basic, 'B'
it_behaves_like :string_unpack_no_platform, 'B'
+ it_behaves_like :string_unpack_taint, 'B'
it "decodes one bit from each byte for each format character starting with the most significant bit" do
[ ["\x00", "B", ["0"]],
@@ -96,6 +98,7 @@ end
describe "String#unpack with format 'b'" do
it_behaves_like :string_unpack_basic, 'b'
it_behaves_like :string_unpack_no_platform, 'b'
+ it_behaves_like :string_unpack_taint, 'b'
it "decodes one bit from each byte for each format character starting with the least significant bit" do
[ ["\x00", "b", ["0"]],
diff --git a/spec/ruby/core/string/unpack/h_spec.rb b/spec/ruby/core/string/unpack/h_spec.rb
index 7d0acf5718..07d52149d1 100644
--- a/spec/ruby/core/string/unpack/h_spec.rb
+++ b/spec/ruby/core/string/unpack/h_spec.rb
@@ -2,10 +2,12 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
+require_relative 'shared/taint'
describe "String#unpack with format 'H'" do
it_behaves_like :string_unpack_basic, 'H'
it_behaves_like :string_unpack_no_platform, 'H'
+ it_behaves_like :string_unpack_taint, 'H'
it "decodes one nibble from each byte for each format character starting with the most significant bit" do
[ ["\x8f", "H", ["8"]],
@@ -66,6 +68,7 @@ end
describe "String#unpack with format 'h'" do
it_behaves_like :string_unpack_basic, 'h'
it_behaves_like :string_unpack_no_platform, 'h'
+ it_behaves_like :string_unpack_taint, 'h'
it "decodes one nibble from each byte for each format character starting with the least significant bit" do
[ ["\x8f", "h", ["f"]],
diff --git a/spec/ruby/core/string/unpack/m_spec.rb b/spec/ruby/core/string/unpack/m_spec.rb
index 0ae1118583..d714f6fbcb 100644
--- a/spec/ruby/core/string/unpack/m_spec.rb
+++ b/spec/ruby/core/string/unpack/m_spec.rb
@@ -2,10 +2,12 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
+require_relative 'shared/taint'
describe "String#unpack with format 'M'" do
it_behaves_like :string_unpack_basic, 'M'
it_behaves_like :string_unpack_no_platform, 'M'
+ it_behaves_like :string_unpack_taint, 'M'
it "decodes an empty string" do
"".unpack("M").should == [""]
@@ -100,6 +102,7 @@ end
describe "String#unpack with format 'm'" do
it_behaves_like :string_unpack_basic, 'm'
it_behaves_like :string_unpack_no_platform, 'm'
+ it_behaves_like :string_unpack_taint, 'm'
it "decodes an empty string" do
"".unpack("m").should == [""]
diff --git a/spec/ruby/core/string/unpack/p_spec.rb b/spec/ruby/core/string/unpack/p_spec.rb
index 57b51fef00..136e32adfd 100644
--- a/spec/ruby/core/string/unpack/p_spec.rb
+++ b/spec/ruby/core/string/unpack/p_spec.rb
@@ -1,21 +1,52 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
+require_relative 'shared/taint'
describe "String#unpack with format 'P'" do
it_behaves_like :string_unpack_basic, 'P'
+ it_behaves_like :string_unpack_taint, 'P'
- it "returns a random object after consuming a size-of a machine word bytes" do
- str = "\0" * 1.size
- str.unpack("P").should be_kind_of(Object)
+ it "round-trips a string through pack and unpack" do
+ ["hello"].pack("P").unpack("P5").should == ["hello"]
+ end
+
+ it "cannot unpack a string except from the same object that created it, or a duplicate of it" do
+ packed = ["hello"].pack("P")
+ packed.unpack("P5").should == ["hello"]
+ packed.dup.unpack("P5").should == ["hello"]
+ lambda { packed.to_sym.to_s.unpack("P5") }.should raise_error(ArgumentError, /no associated pointer/)
+ end
+
+ it "taints the unpacked string" do
+ ["hello"].pack("P").unpack("P5").first.tainted?.should be_true
+ end
+
+ it "reads as many characters as specified" do
+ ["hello"].pack("P").unpack("P1").should == ["h"]
+ end
+
+ it "reads only as far as a NUL character" do
+ ["hello"].pack("P").unpack("P10").should == ["hello"]
end
end
describe "String#unpack with format 'p'" do
it_behaves_like :string_unpack_basic, 'p'
+ it_behaves_like :string_unpack_taint, 'p'
+
+ it "round-trips a string through pack and unpack" do
+ ["hello"].pack("p").unpack("p").should == ["hello"]
+ end
+
+ it "cannot unpack a string except from the same object that created it, or a duplicate of it" do
+ packed = ["hello"].pack("p")
+ packed.unpack("p").should == ["hello"]
+ packed.dup.unpack("p").should == ["hello"]
+ lambda { packed.to_sym.to_s.unpack("p") }.should raise_error(ArgumentError, /no associated pointer/)
+ end
- it "returns a random object after consuming a size-of a machine word bytes" do
- str = "\0" * 1.size
- str.unpack("p").should be_kind_of(Object)
+ it "taints the unpacked string" do
+ ["hello"].pack("p").unpack("p").first.tainted?.should be_true
end
end
diff --git a/spec/ruby/core/string/unpack/shared/taint.rb b/spec/ruby/core/string/unpack/shared/taint.rb
new file mode 100644
index 0000000000..391338192a
--- /dev/null
+++ b/spec/ruby/core/string/unpack/shared/taint.rb
@@ -0,0 +1,81 @@
+describe :string_unpack_taint, shared: true do
+ it "does not taint returned arrays if given an untainted format string" do
+ "".unpack(unpack_format(2)).tainted?.should be_false
+ end
+
+ it "does not taint returned arrays if given a tainted format string" do
+ format_string = unpack_format(2).dup
+ format_string.taint
+ "".unpack(format_string).tainted?.should be_false
+ end
+
+ it "does not taint returned strings if given an untainted format string" do
+ "".unpack(unpack_format(2)).any?(&:tainted?).should be_false
+ end
+
+ it "does not taint returned strings if given a tainted format string" do
+ format_string = unpack_format(2).dup
+ format_string.taint
+ "".unpack(format_string).any?(&:tainted?).should be_false
+ end
+
+ it "does not taint returned arrays if given an untainted packed string" do
+ "".unpack(unpack_format(2)).tainted?.should be_false
+ end
+
+ it "does not taint returned arrays if given a tainted packed string" do
+ packed_string = ""
+ packed_string.taint
+ packed_string.unpack(unpack_format(2)).tainted?.should be_false
+ end
+
+ it "does not taint returned strings if given an untainted packed string" do
+ "".unpack(unpack_format(2)).any?(&:tainted?).should be_false
+ end
+
+ it "taints returned strings if given a tainted packed string" do
+ packed_string = ""
+ packed_string.taint
+ packed_string.unpack(unpack_format(2)).all?(&:tainted?).should be_true
+ end
+
+ it "does not untrust returned arrays if given an untrusted format string" do
+ "".unpack(unpack_format(2)).untrusted?.should be_false
+ end
+
+ it "does not untrust returned arrays if given a untrusted format string" do
+ format_string = unpack_format(2).dup
+ format_string.untrust
+ "".unpack(format_string).untrusted?.should be_false
+ end
+
+ it "does not untrust returned strings if given an untainted format string" do
+ "".unpack(unpack_format(2)).any?(&:untrusted?).should be_false
+ end
+
+ it "does not untrust returned strings if given a untrusted format string" do
+ format_string = unpack_format(2).dup
+ format_string.untrust
+ "".unpack(format_string).any?(&:untrusted?).should be_false
+ end
+
+ it "does not untrust returned arrays if given an trusted packed string" do
+ "".unpack(unpack_format(2)).untrusted?.should be_false
+ end
+
+ it "does not untrust returned arrays if given a untrusted packed string" do
+ packed_string = ""
+ packed_string.untrust
+ packed_string.unpack(unpack_format(2)).untrusted?.should be_false
+ end
+
+ it "does not untrust returned strings if given an trusted packed string" do
+ "".unpack(unpack_format(2)).any?(&:untrusted?).should be_false
+ end
+
+ it "untrusts returned strings if given a untrusted packed string" do
+ packed_string = ""
+ packed_string.untrust
+ packed_string.unpack(unpack_format(2)).all?(&:untrusted?).should be_true
+ end
+end
diff --git a/spec/ruby/core/string/unpack/u_spec.rb b/spec/ruby/core/string/unpack/u_spec.rb
index 6326bd7963..ee1d6c68e7 100644
--- a/spec/ruby/core/string/unpack/u_spec.rb
+++ b/spec/ruby/core/string/unpack/u_spec.rb
@@ -3,11 +3,13 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/unicode'
+require_relative 'shared/taint'
describe "String#unpack with format 'U'" do
it_behaves_like :string_unpack_basic, 'U'
it_behaves_like :string_unpack_no_platform, 'U'
it_behaves_like :string_unpack_unicode, 'U'
+ it_behaves_like :string_unpack_taint, 'U'
it "raises ArgumentError on a malformed byte sequence" do
lambda { "\xE3".unpack('U') }.should raise_error(ArgumentError)
@@ -21,6 +23,7 @@ end
describe "String#unpack with format 'u'" do
it_behaves_like :string_unpack_basic, 'u'
it_behaves_like :string_unpack_no_platform, 'u'
+ it_behaves_like :string_unpack_taint, 'u'
it "decodes an empty string as an empty string" do
"".unpack("u").should == [""]
diff --git a/spec/ruby/core/string/unpack/z_spec.rb b/spec/ruby/core/string/unpack/z_spec.rb
index 67d36ac8bf..2de624a74d 100644
--- a/spec/ruby/core/string/unpack/z_spec.rb
+++ b/spec/ruby/core/string/unpack/z_spec.rb
@@ -3,11 +3,13 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
+require_relative 'shared/taint'
describe "String#unpack with format 'Z'" do
it_behaves_like :string_unpack_basic, 'Z'
it_behaves_like :string_unpack_no_platform, 'Z'
it_behaves_like :string_unpack_string, 'Z'
+ it_behaves_like :string_unpack_taint, 'Z'
it "stops decoding at NULL bytes when passed the '*' modifier" do
"a\x00\x00 b \x00c".unpack('Z*Z*Z*Z*').should == ["a", "", " b ", "c"]
diff --git a/spec/ruby/core/struct/eql_spec.rb b/spec/ruby/core/struct/eql_spec.rb
index 229e81198f..c864b2b943 100644
--- a/spec/ruby/core/struct/eql_spec.rb
+++ b/spec/ruby/core/struct/eql_spec.rb
@@ -8,6 +8,6 @@ describe "Struct#eql?" do
it "returns false if any corresponding elements are not #eql?" do
car = StructClasses::Car.new("Honda", "Accord", 1998)
similar_car = StructClasses::Car.new("Honda", "Accord", 1998.0)
- car.send(@method, similar_car).should be_false
+ car.should_not eql(similar_car)
end
end
diff --git a/spec/ruby/core/thread/backtrace/location/path_spec.rb b/spec/ruby/core/thread/backtrace/location/path_spec.rb
index e493dee8d0..b1a3439747 100644
--- a/spec/ruby/core/thread/backtrace/location/path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/path_spec.rb
@@ -56,7 +56,7 @@ describe 'Thread::Backtrace::Location#path' do
end
context 'when the script is outside of the working directory' do
- before do
+ before :each do
@parent_dir = tmp('path_outside_pwd')
@sub_dir = File.join(@parent_dir, 'sub')
@script = File.join(@parent_dir, 'main.rb')
@@ -67,9 +67,7 @@ describe 'Thread::Backtrace::Location#path' do
cp(source, @script)
end
- after do
- rm_r(@script)
- rm_r(@sub_dir)
+ after :each do
rm_r(@parent_dir)
end
diff --git a/spec/ruby/core/time/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index e0218a2572..eced8a75fb 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -49,6 +49,14 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10").utc_offset.should == -15000
end
+ it "returns a Time with a UTC offset specified as +HH:MM:SS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+05:30:37").utc_offset.should == 19837
+ end
+
+ it "returns a Time with a UTC offset specified as -HH:MM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043
+ end
+
describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do
o = mock('string')
@@ -96,6 +104,14 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, 86400 - 1).utc_offset.should == (86400 - 1)
lambda { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should raise_error(ArgumentError)
end
+
+ it "raises ArgumentError if the seconds argument is negative" do
+ lambda { Time.new(2000, 1, 1, 0, 0, -1) }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do
+ lambda { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError)
+ end
end
ruby_version_is "2.6" do
diff --git a/spec/ruby/language/regexp/back-references_spec.rb b/spec/ruby/language/regexp/back-references_spec.rb
index fb1e1eb594..81015ac21e 100644
--- a/spec/ruby/language/regexp/back-references_spec.rb
+++ b/spec/ruby/language/regexp/back-references_spec.rb
@@ -46,4 +46,8 @@ describe "Regexps with back-references" do
it "resets nested \<n> backreference before match of outer subexpression" do
/(a\1?){2}/.match("aaaa").to_a.should == ["aa", "a"]
end
+
+ it "can match an optional quote, followed by content, followed by a matching quote, as the whole string" do
+ /^("|)(.*)\1$/.match('x').to_a.should == ["x", "", "x"]
+ end
end
diff --git a/spec/ruby/language/regexp_spec.rb b/spec/ruby/language/regexp_spec.rb
index 19f4871e6e..6da29ee7a2 100644
--- a/spec/ruby/language/regexp_spec.rb
+++ b/spec/ruby/language/regexp_spec.rb
@@ -167,4 +167,31 @@ describe "Literal Regexps" do
pattern.to_s.should == ref
end
end
+
+ ruby_version_is '2.4' do
+ it "support handling unicode 9.0 characters with POSIX bracket expressions" do
+ char_lowercase = "\u{104D8}" # OSAGE SMALL LETTER A
+ /[[:lower:]]/.match(char_lowercase).to_s.should == char_lowercase
+ char_uppercase = "\u{104B0}" # OSAGE CAPITAL LETTER A
+ /[[:upper:]]/.match(char_uppercase).to_s.should == char_uppercase
+ end
+ end
+
+ ruby_version_is ""..."2.4" do
+ it "does not support handling unicode 9.0 characters with POSIX bracket expressions" do
+ char_lowercase = "\u{104D8}" # OSAGE SMALL LETTER A
+ /[[:lower:]]/.match(char_lowercase).should == nil
+
+ char_uppercase = "\u{104B0}" # OSAGE CAPITAL LETTER A
+ /[[:upper:]]/.match(char_lowercase).should == nil
+ end
+
+ it "supports handling unicode 8.0 characters with POSIX bracket expressions" do
+ char_lowercase = "\u{A7B5}" # LATIN SMALL LETTER BETA
+ /[[:lower:]]/.match(char_lowercase).to_s.should == char_lowercase
+
+ char_uppercase = "\u{A7B4}" # LATIN CAPITAL LETTER BETA
+ /[[:upper:]]/.match(char_uppercase).to_s.should == char_uppercase
+ end
+ end
end
diff --git a/spec/ruby/library/bigdecimal/divmod_spec.rb b/spec/ruby/library/bigdecimal/divmod_spec.rb
index 22b66c2d48..3a18b150dd 100644
--- a/spec/ruby/library/bigdecimal/divmod_spec.rb
+++ b/spec/ruby/library/bigdecimal/divmod_spec.rb
@@ -38,9 +38,9 @@ describe "BigDecimal#mod_part_of_divmod" do
it "raises ZeroDivisionError if other is zero" do
bd5667 = BigDecimal("5667.19")
- lambda { bd5667.send(@method, 0) }.should raise_error(ZeroDivisionError)
- lambda { bd5667.send(@method, BigDecimal("0")) }.should raise_error(ZeroDivisionError)
- lambda { @zero.send(@method, @zero) }.should raise_error(ZeroDivisionError)
+ lambda { bd5667.mod_part_of_divmod(0) }.should raise_error(ZeroDivisionError)
+ lambda { bd5667.mod_part_of_divmod(BigDecimal("0")) }.should raise_error(ZeroDivisionError)
+ lambda { @zero.mod_part_of_divmod(@zero) }.should raise_error(ZeroDivisionError)
end
end
diff --git a/spec/ruby/library/bigdecimal/to_s_spec.rb b/spec/ruby/library/bigdecimal/to_s_spec.rb
index acc2e943f0..75741c5050 100644
--- a/spec/ruby/library/bigdecimal/to_s_spec.rb
+++ b/spec/ruby/library/bigdecimal/to_s_spec.rb
@@ -15,8 +15,16 @@ describe "BigDecimal#to_s" do
@bigneg.to_s.kind_of?(String).should == true
end
- it "the default format looks like 0.xxxxEnn" do
- @bigdec.to_s.should =~ /^0\.[0-9]*E[0-9]*$/i
+ ruby_version_is ''...'2.4' do
+ it "the default format looks like 0.xxxxEnn" do
+ @bigdec.to_s.should =~ /^0\.[0-9]*E[0-9]*$/
+ end
+ end
+
+ ruby_version_is '2.4' do
+ it "the default format looks like 0.xxxxenn" do
+ @bigdec.to_s.should =~ /^0\.[0-9]*e[0-9]*$/
+ end
end
it "takes an optional argument" do
@@ -63,10 +71,12 @@ describe "BigDecimal#to_s" do
end
it "can use conventional floating point notation" do
- @bigdec.to_s("F").should == @bigdec_str
- @bigneg.to_s("F").should == @bigneg_str
- str2 = "+123.45678901 23456789"
- BigDecimal('123.45678901234567890').to_s('+8F').should == str2
+ %w[f F].each do |format_char|
+ @bigdec.to_s(format_char).should == @bigdec_str
+ @bigneg.to_s(format_char).should == @bigneg_str
+ str2 = "+123.45678901 23456789"
+ BigDecimal('123.45678901234567890').to_s("+8#{format_char}").should == str2
+ end
end
end
diff --git a/spec/ruby/library/datetime/add_spec.rb b/spec/ruby/library/datetime/add_spec.rb
new file mode 100644
index 0000000000..a6d98914bd
--- /dev/null
+++ b/spec/ruby/library/datetime/add_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require 'date'
+
+describe "DateTime#+" do
+ it "is able to add sub-millisecond precision values" do
+ datetime = DateTime.new(2017)
+ (datetime + 0.00001).to_time.usec.should == 864000
+ end
+end
diff --git a/spec/ruby/library/datetime/subtract_spec.rb b/spec/ruby/library/datetime/subtract_spec.rb
new file mode 100644
index 0000000000..ed88533246
--- /dev/null
+++ b/spec/ruby/library/datetime/subtract_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require 'date'
+
+describe "DateTime#-" do
+ it "is able to subtract sub-millisecond precision values" do
+ date = DateTime.new(2017)
+ ((date + 0.00001) - date).should == Rational(1, 100000)
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/open_spec.rb b/spec/ruby/library/socket/unixsocket/open_spec.rb
index 6c4b7c5676..ad5048fedd 100644
--- a/spec/ruby/library/socket/unixsocket/open_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/open_spec.rb
@@ -19,7 +19,7 @@ describe "UNIXSocket.open" do
end
it "opens a unix socket on the specified file and yields it to the block" do
- UNIXSocket.send(@method, @path) do |client|
+ UNIXSocket.open(@path) do |client|
client.addr[0].should == "AF_UNIX"
client.closed?.should == false
end
diff --git a/spec/ruby/library/stringio/getbyte_spec.rb b/spec/ruby/library/stringio/getbyte_spec.rb
index 99737614b9..3daa3d8e02 100644
--- a/spec/ruby/library/stringio/getbyte_spec.rb
+++ b/spec/ruby/library/stringio/getbyte_spec.rb
@@ -8,9 +8,9 @@ describe "StringIO#getbyte" do
it "returns the 8-bit byte at the current position" do
io = StringIO.new("example")
- io.send(@method).should == 101
- io.send(@method).should == 120
- io.send(@method).should == 97
+ io.getbyte.should == 101
+ io.getbyte.should == 120
+ io.getbyte.should == 97
end
end
diff --git a/spec/ruby/library/stringio/getc_spec.rb b/spec/ruby/library/stringio/getc_spec.rb
index 9c0a28a1f0..263d418316 100644
--- a/spec/ruby/library/stringio/getc_spec.rb
+++ b/spec/ruby/library/stringio/getc_spec.rb
@@ -8,9 +8,9 @@ describe "StringIO#getc" do
it "returns the character at the current position" do
io = StringIO.new("example")
- io.send(@method).should == ?e
- io.send(@method).should == ?x
- io.send(@method).should == ?a
+ io.getc.should == ?e
+ io.getc.should == ?x
+ io.getc.should == ?a
end
end
diff --git a/spec/ruby/library/stringio/getch_spec.rb b/spec/ruby/library/stringio/getch_spec.rb
index cd846705de..06670a178c 100644
--- a/spec/ruby/library/stringio/getch_spec.rb
+++ b/spec/ruby/library/stringio/getch_spec.rb
@@ -12,32 +12,32 @@ describe "StringIO#getch" do
it "returns the character at the current position" do
io = StringIO.new("example")
- io.send(@method).should == ?e
- io.send(@method).should == ?x
- io.send(@method).should == ?a
+ io.getch.should == ?e
+ io.getch.should == ?x
+ io.getch.should == ?a
end
with_feature :encoding do
it "increments #pos by the byte size of the character in multibyte strings" do
io = StringIO.new("föóbar")
- io.send(@method); io.pos.should == 1 # "f" has byte size 1
- io.send(@method); io.pos.should == 3 # "ö" has byte size 2
- io.send(@method); io.pos.should == 5 # "ó" has byte size 2
- io.send(@method); io.pos.should == 6 # "b" has byte size 1
+ io.getch; io.pos.should == 1 # "f" has byte size 1
+ io.getch; io.pos.should == 3 # "ö" has byte size 2
+ io.getch; io.pos.should == 5 # "ó" has byte size 2
+ io.getch; io.pos.should == 6 # "b" has byte size 1
end
end
it "returns nil at the end of the string" do
# empty string case
io = StringIO.new("")
- io.send(@method).should == nil
- io.send(@method).should == nil
+ io.getch.should == nil
+ io.getch.should == nil
# non-empty string case
io = StringIO.new("a")
- io.send(@method) # skip one
- io.send(@method).should == nil
+ io.getch # skip one
+ io.getch.should == nil
end
describe "StringIO#getch when self is not readable" do
diff --git a/spec/ruby/library/stringio/readbyte_spec.rb b/spec/ruby/library/stringio/readbyte_spec.rb
index b87b88b9c2..41a0911293 100644
--- a/spec/ruby/library/stringio/readbyte_spec.rb
+++ b/spec/ruby/library/stringio/readbyte_spec.rb
@@ -8,10 +8,10 @@ describe "StringIO#readbyte" do
it "reads the next 8-bit byte from self's current position" do
io = StringIO.new("example")
- io.send(@method).should == 101
+ io.readbyte.should == 101
io.pos = 4
- io.send(@method).should == 112
+ io.readbyte.should == 112
end
end
diff --git a/spec/ruby/library/stringio/readchar_spec.rb b/spec/ruby/library/stringio/readchar_spec.rb
index 1d2ad45b9a..38944819a2 100644
--- a/spec/ruby/library/stringio/readchar_spec.rb
+++ b/spec/ruby/library/stringio/readchar_spec.rb
@@ -8,10 +8,10 @@ describe "StringIO#readchar" do
it "reads the next 8-bit byte from self's current position" do
io = StringIO.new("example")
- io.send(@method).should == ?e
+ io.readchar.should == ?e
io.pos = 4
- io.send(@method).should == ?p
+ io.readchar.should == ?p
end
end
diff --git a/spec/ruby/library/zlib/crc32_spec.rb b/spec/ruby/library/zlib/crc32_spec.rb
index 5c39586ed9..02f95fd92c 100644
--- a/spec/ruby/library/zlib/crc32_spec.rb
+++ b/spec/ruby/library/zlib/crc32_spec.rb
@@ -24,6 +24,8 @@ describe "Zlib.crc32" do
Zlib.crc32(test_string, 1).should == 1809313411
Zlib.crc32(test_string, 2**8).should == 1722745982
Zlib.crc32(test_string, 2**16).should == 1932511220
+ Zlib.crc32("p", ~305419896).should == 4046865307
+ Zlib.crc32("p", -305419897).should == 4046865307
lambda { Zlib.crc32(test_string, 2**128) }.should raise_error(RangeError)
end
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index 88b3e47833..583b33d736 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -139,21 +139,21 @@ describe "C-API Encoding function" do
it_behaves_like :rb_enc_get_index, :rb_enc_get_index
it "returns the index of the encoding of a Symbol" do
- @s.send(@method, :symbol).should >= 0
+ @s.rb_enc_get_index(:symbol).should >= 0
end
it "returns -1 as the index of nil" do
- @s.send(@method, nil).should == -1
+ @s.rb_enc_get_index(nil).should == -1
end
it "returns -1 as the index for immediates" do
- @s.send(@method, 1).should == -1
+ @s.rb_enc_get_index(1).should == -1
end
ruby_version_is "2.6" do
it "returns -1 for an object without an encoding" do
obj = Object.new
- @s.send(@method, obj).should == -1
+ @s.rb_enc_get_index(obj).should == -1
end
end
end
diff --git a/spec/ruby/optional/capi/object_spec.rb b/spec/ruby/optional/capi/object_spec.rb
index 7a817b7436..541b58b48c 100644
--- a/spec/ruby/optional/capi/object_spec.rb
+++ b/spec/ruby/optional/capi/object_spec.rb
@@ -813,6 +813,15 @@ describe "CApiObject" do
it "returns nil if the instance variable has not been initialized" do
@o.rb_ivar_get(@test, :@bar).should == nil
end
+
+ it "returns nil if the instance variable has not been initialized and is not a valid Ruby name" do
+ @o.rb_ivar_get(@test, :bar).should == nil
+ end
+
+ it 'returns the instance variable when it is not a valid Ruby name' do
+ @o.rb_ivar_set(@test, :foo, 27)
+ @o.rb_ivar_get(@test, :foo).should == 27
+ end
end
describe "rb_ivar_set" do
@@ -820,6 +829,15 @@ describe "CApiObject" do
@o.rb_ivar_set(@test, :@foo, 42).should == 42
@test.instance_eval { @foo }.should == 42
end
+
+ it "sets and returns the instance variable on an object" do
+ @o.rb_ivar_set(@test, :@foo, 42).should == 42
+ @test.instance_eval { @foo }.should == 42
+ end
+
+ it 'sets and returns the instance variable when it is not a valid Ruby name' do
+ @o.rb_ivar_set(@test, :foo, 27).should == 27
+ end
end
describe "rb_ivar_defined" do
@@ -830,6 +848,10 @@ describe "CApiObject" do
it "returns false if the instance variable is not defined" do
@o.rb_ivar_defined(@test, :@bar).should == false
end
+
+ it "does not throw an error if the instance variable is not a valid Ruby name" do
+ @o.rb_ivar_defined(@test, :bar).should == false
+ end
end
end
end
diff --git a/spec/ruby/security/cve_2018_16396_spec.rb b/spec/ruby/security/cve_2018_16396_spec.rb
new file mode 100644
index 0000000000..e462e0022d
--- /dev/null
+++ b/spec/ruby/security/cve_2018_16396_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../spec_helper'
+
+describe "Array#pack" do
+
+ it "resists CVE-2018-16396 by tainting output based on input" do
+ "aAZBbHhuMmPp".each_char do |f|
+ ["123456".taint].pack(f).tainted?.should be_true
+ end
+ end
+
+end
+
+describe "String#unpack" do
+
+ it "resists CVE-2018-16396 by tainting output based on input" do
+ "aAZBbHhuMm".each_char do |f|
+ "123456".taint.unpack(f).first.tainted?.should be_true
+ end
+ end
+
+end
diff --git a/spec/ruby/shared/basicobject/send.rb b/spec/ruby/shared/basicobject/send.rb
index f8c63c5522..2b79ab4c2c 100644
--- a/spec/ruby/shared/basicobject/send.rb
+++ b/spec/ruby/shared/basicobject/send.rb
@@ -29,6 +29,13 @@ describe :basicobject_send, shared: true do
SendSpecs::Foo.send(@method, :bar).should == 'done'
end
+ it "raises a TypeError if the method name is not a string or symbol" do
+ -> { SendSpecs.send(@method, nil) }.should raise_error(TypeError, /not a symbol nor a string/)
+ -> { SendSpecs.send(@method, 42) }.should raise_error(TypeError, /not a symbol nor a string/)
+ -> { SendSpecs.send(@method, 3.14) }.should raise_error(TypeError, /not a symbol nor a string/)
+ -> { SendSpecs.send(@method, true) }.should raise_error(TypeError, /not a symbol nor a string/)
+ end
+
it "raises a NameError if the corresponding method can't be found" do
class SendSpecs::Foo
def bar
diff --git a/spec/ruby/shared/kernel/raise.rb b/spec/ruby/shared/kernel/raise.rb
index 70d638fff9..4128a636ad 100644
--- a/spec/ruby/shared/kernel/raise.rb
+++ b/spec/ruby/shared/kernel/raise.rb
@@ -41,7 +41,7 @@ describe :kernel_raise, shared: true do
lambda { @object.raise(nil) }.should raise_error(TypeError)
end
- it "re-raises the rescued exception" do
+ it "re-raises the previously rescued exception if no exception is specified" do
lambda do
begin
raise Exception, "outer"
@@ -60,6 +60,22 @@ describe :kernel_raise, shared: true do
ScratchPad.recorded.should be_nil
end
+ it "re-raises a previously rescued exception without overwriting the backtrace" do
+ begin
+ raise 'raised'
+ rescue => raised
+ begin
+ raise_again_line = __LINE__; raise raised
+ rescue => raised_again
+ # This spec is written using #backtrace and matching the line number
+ # from the string, as backtrace_locations is a more advanced
+ # method that is not always supported by implementations.
+
+ raised_again.backtrace.first.should_not include(":#{raise_again_line}:")
+ end
+ end
+ end
+
it "allows Exception, message, and backtrace parameters" do
lambda do
@object.raise(ArgumentError, "message", caller)