From 4053e8ba0d39b688440fedee2ab3fffabcd64312 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 10 Jan 2022 16:29:54 +0100 Subject: Update to ruby/spec@226cfdc --- spec/ruby/core/array/pack/a_spec.rb | 11 ++++++ spec/ruby/core/array/pack/b_spec.rb | 7 +++- spec/ruby/core/array/pack/h_spec.rb | 5 +++ spec/ruby/core/array/pack/shared/float.rb | 8 ++++ spec/ruby/core/array/pack/u_spec.rb | 10 +++++ spec/ruby/core/array/pack/z_spec.rb | 10 +++++ spec/ruby/core/file/shared/fnmatch.rb | 8 ++++ spec/ruby/core/hash/to_a_spec.rb | 10 +++++ spec/ruby/core/hash/transform_keys_spec.rb | 4 +- spec/ruby/core/integer/constants_spec.rb | 20 ++++++++-- spec/ruby/core/io/ungetc_spec.rb | 2 +- spec/ruby/core/kernel/match_spec.rb | 10 ++++- spec/ruby/core/math/log2_spec.rb | 2 +- spec/ruby/core/module/include_spec.rb | 21 ++++++++++ spec/ruby/core/module/prepend_spec.rb | 2 +- spec/ruby/core/numeric/shared/step.rb | 1 - spec/ruby/core/numeric/step_spec.rb | 2 - spec/ruby/core/proc/compose_spec.rb | 8 ++++ spec/ruby/core/proc/eql_spec.rb | 2 +- spec/ruby/core/proc/equal_value_spec.rb | 2 +- spec/ruby/core/random/default_spec.rb | 32 +++++++++++++++- spec/ruby/core/random/raw_seed_spec.rb | 6 --- spec/ruby/core/random/shared/urandom.rb | 23 ----------- spec/ruby/core/random/urandom_spec.rb | 25 ++++++++++++ spec/ruby/core/string/allocate_spec.rb | 2 +- spec/ruby/core/string/bytesize_spec.rb | 2 +- spec/ruby/core/string/element_set_spec.rb | 6 +++ spec/ruby/core/string/shared/length.rb | 24 ++++++------ spec/ruby/core/string/split_spec.rb | 4 ++ spec/ruby/fixtures/class.rb | 4 ++ spec/ruby/language/case_spec.rb | 9 +++++ spec/ruby/language/class_spec.rb | 13 +++++++ spec/ruby/language/constants_spec.rb | 14 +++++++ spec/ruby/language/def_spec.rb | 2 +- spec/ruby/language/pattern_matching_spec.rb | 59 +++++++++++++++++++++++++++++ spec/ruby/language/variables_spec.rb | 21 +++++----- spec/ruby/library/pp/pp_spec.rb | 7 ++++ spec/ruby/optional/capi/ext/proc_spec.c | 59 +++++++++++++++++++++++++++++ spec/ruby/optional/capi/ext/thread_spec.c | 36 ++++++++++++++++++ spec/ruby/optional/capi/proc_spec.rb | 27 +++++++++++++ spec/ruby/optional/capi/thread_spec.rb | 10 +++++ spec/ruby/security/cve_2019_8322_spec.rb | 24 ++++++------ 42 files changed, 470 insertions(+), 84 deletions(-) delete mode 100644 spec/ruby/core/random/raw_seed_spec.rb delete mode 100644 spec/ruby/core/random/shared/urandom.rb create mode 100644 spec/ruby/core/random/urandom_spec.rb (limited to 'spec') diff --git a/spec/ruby/core/array/pack/a_spec.rb b/spec/ruby/core/array/pack/a_spec.rb index 7af7a16c68..f4a40502c2 100644 --- a/spec/ruby/core/array/pack/a_spec.rb +++ b/spec/ruby/core/array/pack/a_spec.rb @@ -12,6 +12,17 @@ describe "Array#pack with format 'A'" do it_behaves_like :array_pack_string, 'A' it_behaves_like :array_pack_taint, 'A' + it "calls #to_str to convert an Object to a String" do + obj = mock("pack A string") + obj.should_receive(:to_str).and_return("``abcdef") + [obj].pack("A*").should == "``abcdef" + end + + it "will not implicitly convert a number to a string" do + -> { [0].pack('A') }.should raise_error(TypeError) + -> { [0].pack('a') }.should raise_error(TypeError) + end + it "adds all the bytes to the output when passed the '*' modifier" do ["abc"].pack("A*").should == "abc" end diff --git a/spec/ruby/core/array/pack/b_spec.rb b/spec/ruby/core/array/pack/b_spec.rb index 872c1b88d5..ec82b7d1ab 100644 --- a/spec/ruby/core/array/pack/b_spec.rb +++ b/spec/ruby/core/array/pack/b_spec.rb @@ -13,11 +13,16 @@ describe "Array#pack with format 'B'" do it_behaves_like :array_pack_taint, 'B' it "calls #to_str to convert an Object to a String" do - obj = mock("pack H string") + obj = mock("pack B string") obj.should_receive(:to_str).and_return("``abcdef") [obj].pack("B*").should == "\x2a" end + it "will not implicitly convert a number to a string" do + -> { [0].pack('B') }.should raise_error(TypeError) + -> { [0].pack('b') }.should raise_error(TypeError) + end + it "encodes one bit for each character starting with the most significant bit" do [ [["0"], "\x00"], [["1"], "\x80"] diff --git a/spec/ruby/core/array/pack/h_spec.rb b/spec/ruby/core/array/pack/h_spec.rb index 85a875fc8b..2c1dac8d4a 100644 --- a/spec/ruby/core/array/pack/h_spec.rb +++ b/spec/ruby/core/array/pack/h_spec.rb @@ -18,6 +18,11 @@ describe "Array#pack with format 'H'" do [obj].pack("H").should == "\xa0" end + it "will not implicitly convert a number to a string" do + -> { [0].pack('H') }.should raise_error(TypeError) + -> { [0].pack('h') }.should raise_error(TypeError) + end + it "encodes the first character as the most significant nibble when passed no count modifier" do ["ab"].pack("H").should == "\xa0" end diff --git a/spec/ruby/core/array/pack/shared/float.rb b/spec/ruby/core/array/pack/shared/float.rb index c6b194007f..ba174a071a 100644 --- a/spec/ruby/core/array/pack/shared/float.rb +++ b/spec/ruby/core/array/pack/shared/float.rb @@ -53,6 +53,14 @@ describe :array_pack_float_le, shared: true do it "encodes a negative Float outside the range of a single precision float" do [-1e150].pack(pack_format).should == "\x00\x00\x80\xff" end + + it "encodes a bignum as a float" do + [2 ** 65].pack(pack_format).should == [(2 ** 65).to_f].pack(pack_format) + end + + it "encodes a rational as a float" do + [Rational(3, 4)].pack(pack_format).should == [Rational(3, 4).to_f].pack(pack_format) + end end describe :array_pack_float_be, shared: true do diff --git a/spec/ruby/core/array/pack/u_spec.rb b/spec/ruby/core/array/pack/u_spec.rb index fe969cbb2d..b20093a647 100644 --- a/spec/ruby/core/array/pack/u_spec.rb +++ b/spec/ruby/core/array/pack/u_spec.rb @@ -18,6 +18,16 @@ describe "Array#pack with format 'u'" do it_behaves_like :array_pack_arguments, 'u' it_behaves_like :array_pack_taint, 'u' + it "calls #to_str to convert an Object to a String" do + obj = mock("pack u string") + obj.should_receive(:to_str).and_return("``abcdef") + [obj].pack("u*").should == "(8&!A8F-D968`\n" + end + + it "will not implicitly convert a number to a string" do + -> { [0].pack('u') }.should raise_error(TypeError) + end + it "encodes an empty string as an empty string" do [""].pack("u").should == "" end diff --git a/spec/ruby/core/array/pack/z_spec.rb b/spec/ruby/core/array/pack/z_spec.rb index 82ce7b4a1c..5ad3afd69e 100644 --- a/spec/ruby/core/array/pack/z_spec.rb +++ b/spec/ruby/core/array/pack/z_spec.rb @@ -12,6 +12,16 @@ describe "Array#pack with format 'Z'" do it_behaves_like :array_pack_string, 'Z' it_behaves_like :array_pack_taint, 'Z' + it "calls #to_str to convert an Object to a String" do + obj = mock("pack Z string") + obj.should_receive(:to_str).and_return("``abcdef") + [obj].pack("Z*").should == "``abcdef\x00" + end + + it "will not implicitly convert a number to a string" do + -> { [0].pack('Z') }.should raise_error(TypeError) + end + it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do ["abc"].pack("Z*").should == "abc\x00" end diff --git a/spec/ruby/core/file/shared/fnmatch.rb b/spec/ruby/core/file/shared/fnmatch.rb index a8488fd30a..00682bb64c 100644 --- a/spec/ruby/core/file/shared/fnmatch.rb +++ b/spec/ruby/core/file/shared/fnmatch.rb @@ -75,6 +75,14 @@ describe :file_fnmatch, shared: true do File.send(@method, 'c*t', 'c/a/b/t').should == true end + it "does not match unterminated range of characters" do + File.send(@method, 'abc[de', 'abcd').should == false + end + + it "does not match unterminated range of characters as a literal" do + File.send(@method, 'abc[de', 'abc[de').should == false + end + it "matches ranges of characters using bracket expression (e.g. [a-z])" do File.send(@method, 'ca[a-z]', 'cat').should == true end diff --git a/spec/ruby/core/hash/to_a_spec.rb b/spec/ruby/core/hash/to_a_spec.rb index 46f871389a..6f6f74f73b 100644 --- a/spec/ruby/core/hash/to_a_spec.rb +++ b/spec/ruby/core/hash/to_a_spec.rb @@ -36,4 +36,14 @@ describe "Hash#to_a" do {}.untrust.to_a.untrusted?.should be_true end end + + ruby_version_is '2.7'...'3.0' do + it "returns a not tainted array if self is tainted" do + {}.taint.to_a.tainted?.should be_false + end + + it "returns a trusted array if self is untrusted" do + {}.untrust.to_a.untrusted?.should be_false + end + end end diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb index 8ee1a2cd6d..1e82ff6547 100644 --- a/spec/ruby/core/hash/transform_keys_spec.rb +++ b/spec/ruby/core/hash/transform_keys_spec.rb @@ -80,7 +80,7 @@ describe "Hash#transform_keys!" do end ruby_version_is ""..."3.0.2" do # https://bugs.ruby-lang.org/issues/17735 - it "returns the processed keys if we broke from the block" do + it "returns the processed keys if we break from the block" do @hash.transform_keys! do |v| break if v == :c v.succ @@ -90,7 +90,7 @@ describe "Hash#transform_keys!" do end ruby_version_is "3.0.2" do - it "returns the processed keys and non evaluated keys if we broke from the block" do + it "returns the processed keys and non evaluated keys if we break from the block" do @hash.transform_keys! do |v| break if v == :c v.succ diff --git a/spec/ruby/core/integer/constants_spec.rb b/spec/ruby/core/integer/constants_spec.rb index 2aaa659d5a..2077ad451e 100644 --- a/spec/ruby/core/integer/constants_spec.rb +++ b/spec/ruby/core/integer/constants_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -ruby_version_is ""..."3.1" do - describe "Fixnum" do +describe "Fixnum" do + ruby_version_is ""..."3.2" do it "is unified into Integer" do suppress_warning do Fixnum.should equal(Integer) @@ -13,7 +13,15 @@ ruby_version_is ""..."3.1" do end end - describe "Bignum" do + ruby_version_is "3.2" do + it "is no longer defined" do + Object.should_not.const_defined?(:Fixnum) + end + end +end + +describe "Bignum" do + ruby_version_is ""..."3.2" do it "is unified into Integer" do suppress_warning do Bignum.should equal(Integer) @@ -24,4 +32,10 @@ ruby_version_is ""..."3.1" do -> { Bignum }.should complain(/constant ::Bignum is deprecated/) end end + + ruby_version_is "3.2" do + it "is no longer defined" do + Object.should_not.const_defined?(:Bignum) + end + end end diff --git a/spec/ruby/core/io/ungetc_spec.rb b/spec/ruby/core/io/ungetc_spec.rb index a05d80ee9c..41a455c836 100644 --- a/spec/ruby/core/io/ungetc_spec.rb +++ b/spec/ruby/core/io/ungetc_spec.rb @@ -103,7 +103,7 @@ describe "IO#ungetc" do -> { @io.sysread(1) }.should raise_error(IOError) end - ruby_version_is "0"..."3.0" do + ruby_version_is ""..."3.0" do it "does not affect the stream and returns nil when passed nil" do @io.getc.should == ?V @io.ungetc(nil) diff --git a/spec/ruby/core/kernel/match_spec.rb b/spec/ruby/core/kernel/match_spec.rb index 6c81ed8256..aa25006163 100644 --- a/spec/ruby/core/kernel/match_spec.rb +++ b/spec/ruby/core/kernel/match_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -ruby_version_is ''...'3.2' do - describe "Kernel#=~" do +describe "Kernel#=~" do + ruby_version_is ''...'3.2' do it "returns nil matching any object" do o = Object.new @@ -21,4 +21,10 @@ ruby_version_is ''...'3.2' do end.should complain(/deprecated Object#=~ is called on Object/, verbose: true) end end + + ruby_version_is '3.2' do + it "is no longer defined" do + Object.new.should_not.respond_to?(:=~) + end + end end diff --git a/spec/ruby/core/math/log2_spec.rb b/spec/ruby/core/math/log2_spec.rb index 1594f2d7af..3d4d41d130 100644 --- a/spec/ruby/core/math/log2_spec.rb +++ b/spec/ruby/core/math/log2_spec.rb @@ -15,7 +15,7 @@ describe "Math.log2" do Math.log2((2**301+45677544234809571)).should == 301.0 end - it "raises an Errno::EDOM if the argument is less than 0" do + it "raises Math::DomainError if the argument is less than 0" do -> { Math.log2(-1e-15) }.should raise_error( Math::DomainError) end diff --git a/spec/ruby/core/module/include_spec.rb b/spec/ruby/core/module/include_spec.rb index 128b9af2bf..c47e052d22 100644 --- a/spec/ruby/core/module/include_spec.rb +++ b/spec/ruby/core/module/include_spec.rb @@ -532,6 +532,27 @@ describe "Module#include" do B.foo.should == 'n' end end + + it "overrides a previous super method call" do + c1 = Class.new do + def foo + [:c1] + end + end + c2 = Class.new(c1) do + def foo + [:c2] + super + end + end + c2.new.foo.should == [:c2, :c1] + m = Module.new do + def foo + [:m1] + end + end + c2.include(m) + c2.new.foo.should == [:c2, :m1] + end end describe "Module#include?" do diff --git a/spec/ruby/core/module/prepend_spec.rb b/spec/ruby/core/module/prepend_spec.rb index 04cc27d472..d636e023ed 100644 --- a/spec/ruby/core/module/prepend_spec.rb +++ b/spec/ruby/core/module/prepend_spec.rb @@ -499,7 +499,7 @@ describe "Module#prepend" do c.dup.new.should be_kind_of(m) end - ruby_version_is '0'...'3.0' do + ruby_version_is ''...'3.0' do it "keeps the module in the chain when dupping an intermediate module" do m1 = Module.new { def calc(x) x end } m2 = Module.new { prepend(m1) } diff --git a/spec/ruby/core/numeric/shared/step.rb b/spec/ruby/core/numeric/shared/step.rb index a4fe74f9db..8b1a7bf307 100644 --- a/spec/ruby/core/numeric/shared/step.rb +++ b/spec/ruby/core/numeric/shared/step.rb @@ -256,7 +256,6 @@ describe :numeric_step, :shared => true do end describe "when no block is given" do - step_enum_class = Enumerator step_enum_class = Enumerator::ArithmeticSequence ruby_version_is ""..."3.0" do diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb index 03af8b0e4d..095c474fec 100644 --- a/spec/ruby/core/numeric/step_spec.rb +++ b/spec/ruby/core/numeric/step_spec.rb @@ -21,7 +21,6 @@ describe "Numeric#step" do it_behaves_like :numeric_step, :step describe "when no block is given" do - step_enum_class = Enumerator step_enum_class = Enumerator::ArithmeticSequence ruby_version_is ""..."3.0" do @@ -61,7 +60,6 @@ describe "Numeric#step" do end end end - end describe 'with keyword arguments' do diff --git a/spec/ruby/core/proc/compose_spec.rb b/spec/ruby/core/proc/compose_spec.rb index 803a32af7b..94814d11bc 100644 --- a/spec/ruby/core/proc/compose_spec.rb +++ b/spec/ruby/core/proc/compose_spec.rb @@ -61,9 +61,17 @@ describe "Proc#<<" do g = proc { |x| x + x } lambda_proc = -> x { x } + # lambda << proc (f << g).is_a?(Proc).should == true (f << g).should_not.lambda? + + # lambda << lambda + (f << lambda_proc).is_a?(Proc).should == true (f << lambda_proc).should.lambda? + + # proc << lambda + (g << f).is_a?(Proc).should == true + (g << f).should.lambda? end end diff --git a/spec/ruby/core/proc/eql_spec.rb b/spec/ruby/core/proc/eql_spec.rb index 5f38af72d9..06aee272e5 100644 --- a/spec/ruby/core/proc/eql_spec.rb +++ b/spec/ruby/core/proc/eql_spec.rb @@ -2,7 +2,7 @@ require_relative '../../spec_helper' require_relative 'shared/equal' describe "Proc#eql?" do - ruby_version_is "0"..."3.0" do + ruby_version_is ""..."3.0" do it_behaves_like :proc_equal_undefined, :eql? end diff --git a/spec/ruby/core/proc/equal_value_spec.rb b/spec/ruby/core/proc/equal_value_spec.rb index 4c336331d7..ee88c0537d 100644 --- a/spec/ruby/core/proc/equal_value_spec.rb +++ b/spec/ruby/core/proc/equal_value_spec.rb @@ -2,7 +2,7 @@ require_relative '../../spec_helper' require_relative 'shared/equal' describe "Proc#==" do - ruby_version_is "0"..."3.0" do + ruby_version_is ""..."3.0" do it_behaves_like :proc_equal_undefined, :== end diff --git a/spec/ruby/core/random/default_spec.rb b/spec/ruby/core/random/default_spec.rb index f9270ac7bb..b4ffcb81f4 100644 --- a/spec/ruby/core/random/default_spec.rb +++ b/spec/ruby/core/random/default_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -ruby_version_is ''...'3.2' do - describe "Random::DEFAULT" do +describe "Random::DEFAULT" do + ruby_version_is ''...'3.2' do it "returns a random number generator" do suppress_warning do Random::DEFAULT.should respond_to(:rand) @@ -13,5 +13,33 @@ ruby_version_is ''...'3.2' do seed2 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems') seed1.should != seed2 end + + ruby_version_is ''...'3.0' do + it "returns a Random instance" do + suppress_warning do + Random::DEFAULT.should be_an_instance_of(Random) + end + end + end + + ruby_version_is '3.0' do + it "refers to the Random class" do + suppress_warning do + Random::DEFAULT.should.equal?(Random) + end + end + + it "is deprecated" do + -> { + Random::DEFAULT.should.equal?(Random) + }.should complain(/constant Random::DEFAULT is deprecated/) + end + end + end + + ruby_version_is '3.2' do + it "is no longer defined" do + Random.should_not.const_defined?(:DEFAULT) + end end end diff --git a/spec/ruby/core/random/raw_seed_spec.rb b/spec/ruby/core/random/raw_seed_spec.rb deleted file mode 100644 index 0e40ed0796..0000000000 --- a/spec/ruby/core/random/raw_seed_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'shared/urandom' - -describe "Random.urandom" do - it_behaves_like :random_urandom, :urandom -end diff --git a/spec/ruby/core/random/shared/urandom.rb b/spec/ruby/core/random/shared/urandom.rb deleted file mode 100644 index 159716075c..0000000000 --- a/spec/ruby/core/random/shared/urandom.rb +++ /dev/null @@ -1,23 +0,0 @@ -describe :random_urandom, shared: true do - it "returns a String" do - Random.send(@method, 1).should be_an_instance_of(String) - end - - it "returns a String of the length given as argument" do - Random.send(@method, 15).length.should == 15 - end - - it "raises an ArgumentError on a negative size" do - -> { - Random.send(@method, -1) - }.should raise_error(ArgumentError) - end - - it "returns a binary String" do - Random.send(@method, 15).encoding.should == Encoding::BINARY - end - - it "returns a random binary String" do - Random.send(@method, 12).should_not == Random.send(@method, 12) - end -end diff --git a/spec/ruby/core/random/urandom_spec.rb b/spec/ruby/core/random/urandom_spec.rb new file mode 100644 index 0000000000..6f180e54ac --- /dev/null +++ b/spec/ruby/core/random/urandom_spec.rb @@ -0,0 +1,25 @@ +require_relative '../../spec_helper' + +describe "Random.urandom" do + it "returns a String" do + Random.urandom(1).should be_an_instance_of(String) + end + + it "returns a String of the length given as argument" do + Random.urandom(15).length.should == 15 + end + + it "raises an ArgumentError on a negative size" do + -> { + Random.urandom(-1) + }.should raise_error(ArgumentError) + end + + it "returns a binary String" do + Random.urandom(15).encoding.should == Encoding::BINARY + end + + it "returns a random binary String" do + Random.urandom(12).should_not == Random.urandom(12) + end +end diff --git a/spec/ruby/core/string/allocate_spec.rb b/spec/ruby/core/string/allocate_spec.rb index 5b36b4fd05..30d5f60594 100644 --- a/spec/ruby/core/string/allocate_spec.rb +++ b/spec/ruby/core/string/allocate_spec.rb @@ -14,6 +14,6 @@ describe "String.allocate" do end it "returns a binary String" do - String.new.encoding.should == Encoding::BINARY + String.allocate.encoding.should == Encoding::BINARY end end diff --git a/spec/ruby/core/string/bytesize_spec.rb b/spec/ruby/core/string/bytesize_spec.rb index b8b07cfbec..a31f3ae671 100644 --- a/spec/ruby/core/string/bytesize_spec.rb +++ b/spec/ruby/core/string/bytesize_spec.rb @@ -2,7 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe "#String#bytesize" do +describe "String#bytesize" do it "returns the length of self in bytes" do "hello".bytesize.should == 5 " ".bytesize.should == 1 diff --git a/spec/ruby/core/string/element_set_spec.rb b/spec/ruby/core/string/element_set_spec.rb index c9e02a7381..0aabbacd0e 100644 --- a/spec/ruby/core/string/element_set_spec.rb +++ b/spec/ruby/core/string/element_set_spec.rb @@ -141,6 +141,12 @@ describe "String#[]= with Integer index" do str.encoding.should equal(Encoding::BINARY) end + it "updates the string to a compatible encoding" do + str = " " + str[1] = [0xB9].pack("C*") + str.encoding.should == Encoding::ASCII_8BIT + end + it "raises an Encoding::CompatibilityError if the replacement encoding is incompatible" do str = "あれ" rep = "が".encode Encoding::EUC_JP diff --git a/spec/ruby/core/string/shared/length.rb b/spec/ruby/core/string/shared/length.rb index e931961455..94e5ec135b 100644 --- a/spec/ruby/core/string/shared/length.rb +++ b/spec/ruby/core/string/shared/length.rb @@ -12,9 +12,9 @@ describe :string_length, shared: true do it "returns the length of a string in different encodings" do utf8_str = 'こにちわ' * 100 - utf8_str.size.should == 400 - utf8_str.encode(Encoding::UTF_32BE).size.should == 400 - utf8_str.encode(Encoding::SHIFT_JIS).size.should == 400 + utf8_str.send(@method).should == 400 + utf8_str.encode(Encoding::UTF_32BE).send(@method).should == 400 + utf8_str.encode(Encoding::SHIFT_JIS).send(@method).should == 400 end it "returns the length of the new self after encoding is changed" do @@ -32,24 +32,24 @@ describe :string_length, shared: true do concat.encoding.should == Encoding::UTF_8 concat.bytesize.should == 4 - concat.size.should == 2 + concat.send(@method).should == 2 concat.force_encoding(Encoding::ASCII_8BIT) - concat.size.should == 4 + concat.send(@method).should == 4 end it "adds 1 for every invalid byte in UTF-8" do - "\xF4\x90\x80\x80".size.should == 4 - "a\xF4\x90\x80\x80b".size.should == 6 - "é\xF4\x90\x80\x80è".size.should == 6 + "\xF4\x90\x80\x80".send(@method).should == 4 + "a\xF4\x90\x80\x80b".send(@method).should == 6 + "é\xF4\x90\x80\x80è".send(@method).should == 6 end it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do - "\x00\xd8".force_encoding("UTF-16LE").size.should == 1 - "\xd8\x00".force_encoding("UTF-16BE").size.should == 1 + "\x00\xd8".force_encoding("UTF-16LE").send(@method).should == 1 + "\xd8\x00".force_encoding("UTF-16BE").send(@method).should == 1 end it "adds 1 for a broken sequence in UTF-32" do - "\x04\x03\x02\x01".force_encoding("UTF-32LE").size.should == 1 - "\x01\x02\x03\x04".force_encoding("UTF-32BE").size.should == 1 + "\x04\x03\x02\x01".force_encoding("UTF-32LE").send(@method).should == 1 + "\x01\x02\x03\x04".force_encoding("UTF-32BE").send(@method).should == 1 end end diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb index a373be360d..94f6c9aaee 100644 --- a/spec/ruby/core/string/split_spec.rb +++ b/spec/ruby/core/string/split_spec.rb @@ -62,6 +62,10 @@ describe "String#split with String" do ",".split(",", -1).should == ["", ""] end + it "raises a RangeError when the limit is larger than int" do + -> { "a,b".split(" ", 2147483649) }.should raise_error(RangeError) + end + it "defaults to $; when string isn't given or nil" do suppress_warning do old_fs = $; diff --git a/spec/ruby/fixtures/class.rb b/spec/ruby/fixtures/class.rb index 68fbca7ba7..98cb6c82a2 100644 --- a/spec/ruby/fixtures/class.rb +++ b/spec/ruby/fixtures/class.rb @@ -122,6 +122,10 @@ module ClassSpecs end end end + + DEFINE_CLASS = -> do + class ::A; end + end end class Class diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb index 410cb9afb1..bf06803764 100644 --- a/spec/ruby/language/case_spec.rb +++ b/spec/ruby/language/case_spec.rb @@ -156,6 +156,15 @@ describe "The 'case'-construct" do end.should == "foo" end + it "tests an empty array" do + case [] + when [] + 'foo' + else + 'bar' + end.should == 'foo' + end + it "expands arrays to lists of values" do case 'z' when *['a', 'b', 'c', 'd'] diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb index 83db164e1a..877895bf15 100644 --- a/spec/ruby/language/class_spec.rb +++ b/spec/ruby/language/class_spec.rb @@ -17,6 +17,19 @@ describe "The class keyword" do eval "class ClassSpecsKeywordWithoutSemicolon end" ClassSpecsKeywordWithoutSemicolon.should be_an_instance_of(Class) end + + it "can redefine a class when called from a block" do + ClassSpecs::DEFINE_CLASS.call + A.should be_an_instance_of(Class) + + Object.send(:remove_const, :A) + defined?(A).should be_nil + + ClassSpecs::DEFINE_CLASS.call + A.should be_an_instance_of(Class) + ensure + Object.send(:remove_const, :A) if defined?(::A) + end end describe "A class definition" do diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb index 03f1272401..bc76c60d20 100644 --- a/spec/ruby/language/constants_spec.rb +++ b/spec/ruby/language/constants_spec.rb @@ -718,3 +718,17 @@ describe 'Allowed characters' do eval("mod::ἍBB").should == 1 end end + +describe 'Assignment' do + context 'dynamic assignment' do + it 'raises SyntaxError' do + -> do + eval <<-CODE + def test + B = 1 + end + CODE + end.should raise_error(SyntaxError, /dynamic constant assignment/) + end + end +end diff --git a/spec/ruby/language/def_spec.rb b/spec/ruby/language/def_spec.rb index 6b0be19d90..d72f8fa888 100644 --- a/spec/ruby/language/def_spec.rb +++ b/spec/ruby/language/def_spec.rb @@ -213,7 +213,7 @@ describe "An instance method with a default argument" do end ruby_version_is '2.7' do - it "raises a syntaxError an existing method with the same name as the local variable" do + it "raises a SyntaxError when there is an existing method with the same name as the local variable" do def bar 1 end diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb index e4abae9412..5f5e2f4902 100644 --- a/spec/ruby/language/pattern_matching_spec.rb +++ b/spec/ruby/language/pattern_matching_spec.rb @@ -1297,6 +1297,65 @@ ruby_version_is "2.7" do a RUBY end + + it "supports pinning instance variables" do + eval(<<~RUBY).should == true + @a = /a/ + case 'abc' + in ^@a + true + end + RUBY + end + + it "supports pinning class variables" do + result = nil + Module.new do + result = module_eval(<<~RUBY) + @@a = 0..10 + + case 2 + in ^@@a + true + end + RUBY + end + + result.should == true + end + + it "supports pinning global variables" do + eval(<<~RUBY).should == true + $a = /a/ + case 'abc' + in ^$a + true + end + RUBY + end + + it "supports pinning expressions" do + eval(<<~RUBY).should == true + case 'abc' + in ^(/a/) + true + end + RUBY + + eval(<<~RUBY).should == true + case {name: '2.6', released_at: Time.new(2018, 12, 25)} + in {released_at: ^(Time.new(2010)..Time.new(2020))} + true + end + RUBY + + eval(<<~RUBY).should == true + case 0 + in ^(0+0) + true + end + RUBY + end end end end diff --git a/spec/ruby/language/variables_spec.rb b/spec/ruby/language/variables_spec.rb index 699187335c..431c5aca99 100644 --- a/spec/ruby/language/variables_spec.rb +++ b/spec/ruby/language/variables_spec.rb @@ -797,17 +797,6 @@ describe 'Local variable shadowing' do end describe 'Allowed characters' do - # new feature in 2.6 -- https://bugs.ruby-lang.org/issues/13770 - it 'does not allow non-ASCII upcased characters at the beginning' do - -> do - eval <<-CODE - def test - ἍBB = 1 - end - CODE - end.should raise_error(SyntaxError, /dynamic constant assignment/) - end - it 'allows non-ASCII lowercased characters at the beginning' do result = nil @@ -821,6 +810,16 @@ describe 'Allowed characters' do result.should == 1 end + + it 'parses a non-ASCII upcased character as a constant identifier' do + -> do + eval <<-CODE + def test + ἍBB = 1 + end + CODE + end.should raise_error(SyntaxError, /dynamic constant assignment/) + end end describe "Instance variables" do diff --git a/spec/ruby/library/pp/pp_spec.rb b/spec/ruby/library/pp/pp_spec.rb index 06b22601d8..243478efd9 100644 --- a/spec/ruby/library/pp/pp_spec.rb +++ b/spec/ruby/library/pp/pp_spec.rb @@ -20,4 +20,11 @@ describe "PP.pp" do other_out.to_s.should == "[1, 2, 3]\n" end + + it 'correctly prints a Hash' do + hash = { 'key' => 42 } + -> { + PP.pp hash + }.should output('{"key"=>42}' + "\n") + end end diff --git a/spec/ruby/optional/capi/ext/proc_spec.c b/spec/ruby/optional/capi/ext/proc_spec.c index e0bd8b1bbc..1137f4156b 100644 --- a/spec/ruby/optional/capi/ext/proc_spec.c +++ b/spec/ruby/optional/capi/ext/proc_spec.c @@ -11,10 +11,63 @@ VALUE proc_spec_rb_proc_new_function(RB_BLOCK_CALL_FUNC_ARGLIST(args, dummy)) { return rb_funcall(args, rb_intern("inspect"), 0); } +VALUE proc_spec_rb_proc_new_function_arg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) { + return arg; +} + +VALUE proc_spec_rb_proc_new_function_argc(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) { + return INT2FIX(argc); +} + +VALUE proc_spec_rb_proc_new_function_argv_n(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) { + int n = FIX2INT(arg); + if (n < argc) { + return argv[n]; + } else { + rb_exc_raise(rb_exc_new2(rb_eArgError, "Arg index out of bounds.")); + } +} + +VALUE proc_spec_rb_proc_new_function_callback_arg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) { + return callback_arg; +} + +VALUE proc_spec_rb_proc_new_function_blockarg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) { + return blockarg; +} + +VALUE proc_spec_rb_proc_new_function_block_given_p(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) { + return rb_block_given_p() ? Qtrue : Qfalse; +} + VALUE proc_spec_rb_proc_new(VALUE self) { return rb_proc_new(proc_spec_rb_proc_new_function, Qnil); } +VALUE proc_spec_rb_proc_new_arg(VALUE self) { + return rb_proc_new(proc_spec_rb_proc_new_function_arg, Qnil); +} + +VALUE proc_spec_rb_proc_new_argc(VALUE self) { + return rb_proc_new(proc_spec_rb_proc_new_function_argc, Qnil); +} + +VALUE proc_spec_rb_proc_new_argv_n(VALUE self) { + return rb_proc_new(proc_spec_rb_proc_new_function_argv_n, Qnil); +} + +VALUE proc_spec_rb_proc_new_callback_arg(VALUE self, VALUE arg) { + return rb_proc_new(proc_spec_rb_proc_new_function_callback_arg, arg); +} + +VALUE proc_spec_rb_proc_new_blockarg(VALUE self) { + return rb_proc_new(proc_spec_rb_proc_new_function_blockarg, Qnil); +} + +VALUE proc_spec_rb_proc_new_block_given_p(VALUE self) { + return rb_proc_new(proc_spec_rb_proc_new_function_block_given_p, Qnil); +} + VALUE proc_spec_rb_proc_arity(VALUE self, VALUE prc) { return INT2FIX(rb_proc_arity(prc)); } @@ -62,6 +115,12 @@ VALUE proc_spec_rb_Proc_new(VALUE self, VALUE scenario) { void Init_proc_spec(void) { VALUE cls = rb_define_class("CApiProcSpecs", rb_cObject); rb_define_method(cls, "rb_proc_new", proc_spec_rb_proc_new, 0); + rb_define_method(cls, "rb_proc_new_arg", proc_spec_rb_proc_new_arg, 0); + rb_define_method(cls, "rb_proc_new_argc", proc_spec_rb_proc_new_argc, 0); + rb_define_method(cls, "rb_proc_new_argv_n", proc_spec_rb_proc_new_argv_n, 0); + rb_define_method(cls, "rb_proc_new_callback_arg", proc_spec_rb_proc_new_callback_arg, 1); + rb_define_method(cls, "rb_proc_new_blockarg", proc_spec_rb_proc_new_blockarg, 0); + rb_define_method(cls, "rb_proc_new_block_given_p", proc_spec_rb_proc_new_block_given_p, 0); rb_define_method(cls, "rb_proc_arity", proc_spec_rb_proc_arity, 1); rb_define_method(cls, "rb_proc_call", proc_spec_rb_proc_call, 2); rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1); diff --git a/spec/ruby/optional/capi/ext/thread_spec.c b/spec/ruby/optional/capi/ext/thread_spec.c index 21f98dec52..bab5fcc211 100644 --- a/spec/ruby/optional/capi/ext/thread_spec.c +++ b/spec/ruby/optional/capi/ext/thread_spec.c @@ -11,6 +11,10 @@ #define pipe(p) rb_w32_pipe(p) #endif +#ifndef _WIN32 +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -131,6 +135,36 @@ static VALUE thread_spec_rb_thread_create(VALUE self, VALUE proc, VALUE arg) { return rb_thread_create(thread_spec_call_proc, (void*)args); } +static VALUE thread_spec_ruby_native_thread_p(VALUE self) { + if (ruby_native_thread_p()) { + return Qtrue; + } else { + return Qfalse; + } +} + +static VALUE false_result = Qfalse; +static VALUE true_result = Qtrue; + +static void *new_thread_check(void *args) { + if (ruby_native_thread_p()) { + return &true_result; + } else { + return &false_result; + } +} + +static VALUE thread_spec_ruby_native_thread_p_new_thread(VALUE self) { +#ifndef _WIN32 + pthread_t t; + VALUE *result = &true_result; + pthread_create(&t, NULL, new_thread_check, NULL); + pthread_join(t, (void **)&result); + return *result; +#else + return Qfalse; +#endif +} void Init_thread_spec(void) { VALUE cls = rb_define_class("CApiThreadSpecs", rb_cObject); @@ -143,6 +177,8 @@ void Init_thread_spec(void) { rb_define_method(cls, "rb_thread_wakeup", thread_spec_rb_thread_wakeup, 1); rb_define_method(cls, "rb_thread_wait_for", thread_spec_rb_thread_wait_for, 2); rb_define_method(cls, "rb_thread_create", thread_spec_rb_thread_create, 2); + rb_define_method(cls, "ruby_native_thread_p", thread_spec_ruby_native_thread_p, 0); + rb_define_method(cls, "ruby_native_thread_p_new_thread", thread_spec_ruby_native_thread_p_new_thread, 0); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/proc_spec.rb b/spec/ruby/optional/capi/proc_spec.rb index 6e797fdeb4..dab143fbe7 100644 --- a/spec/ruby/optional/capi/proc_spec.rb +++ b/spec/ruby/optional/capi/proc_spec.rb @@ -7,6 +7,8 @@ describe "C-API Proc function" do before :each do @p = CApiProcSpecs.new @prc = @p.rb_proc_new + @prc2 = @p.rb_proc_new_argv_n + @prc3 = @p.rb_proc_new_argc end describe "rb_proc_new" do @@ -15,6 +17,7 @@ describe "C-API Proc function" do end it "calls the C function wrapped by the Proc instance when sent #call" do + @p.rb_proc_new_arg.call().should == nil @prc.call(:foo_bar).should == ":foo_bar" @prc.call([:foo, :bar]).should == "[:foo, :bar]" end @@ -24,6 +27,30 @@ describe "C-API Proc function" do @prc[[:foo, :bar]].should == "[:foo, :bar]" end + it "calls the C function with the arg count in argc" do + @prc3.call().should == 0 + @prc3.call(:foo).should == 1 + @prc3.call(:foo, :bar).should == 2 + end + + it "calls the C function with arguments in argv" do + @prc2.call(1, :foo).should == :foo + @prc2.call(2, :foo, :bar).should == :bar + -> { @prc2.call(3, :foo, :bar) }.should raise_error(ArgumentError) + end + + it "calls the C function with the block passed in blockarg" do + a_block = :foo.to_proc + @p.rb_proc_new_blockarg.call(&a_block).should == a_block + @p.rb_proc_new_blockarg.call().should == nil + end + + it "calls the C function and yields to the block passed in blockarg" do + @p.rb_proc_new_block_given_p.call() do + end.should == false + @p.rb_proc_new_block_given_p.call().should == false + end + it "returns a Proc instance correctly described in #inspect without source location" do @prc.inspect.should =~ /^#$/ end diff --git a/spec/ruby/optional/capi/thread_spec.rb b/spec/ruby/optional/capi/thread_spec.rb index 30e29681eb..5cb46bbb7c 100644 --- a/spec/ruby/optional/capi/thread_spec.rb +++ b/spec/ruby/optional/capi/thread_spec.rb @@ -101,6 +101,16 @@ describe "C-API Thread function" do end end + describe "ruby_native_thread_p" do + it "returns non-zero for a ruby thread" do + @t.ruby_native_thread_p.should be_true + end + + it "returns zero for a non ruby thread" do + @t.ruby_native_thread_p_new_thread.should be_false + end + end + describe "rb_thread_call_without_gvl" do it "runs a C function with the global lock unlocked and can be woken by Thread#wakeup" do thr = Thread.new do diff --git a/spec/ruby/security/cve_2019_8322_spec.rb b/spec/ruby/security/cve_2019_8322_spec.rb index b70d78c033..a84d7a5a95 100644 --- a/spec/ruby/security/cve_2019_8322_spec.rb +++ b/spec/ruby/security/cve_2019_8322_spec.rb @@ -5,17 +5,19 @@ require 'rubygems' require 'rubygems/safe_yaml' require 'rubygems/commands/owner_command' -describe "CVE-2019-8322 is resisted by" do - it "sanitising owner names" do - command = Gem::Commands::OwnerCommand.new - def command.rubygems_api_request(*args) - Struct.new(:body).new("---\n- email: \"\e]2;nyan\a\"\n handle: handle\n id: id\n") +platform_is_not :darwin do # frequent timeout/hang on macOS + describe "CVE-2019-8322 is resisted by" do + it "sanitising owner names" do + command = Gem::Commands::OwnerCommand.new + def command.rubygems_api_request(*args) + Struct.new(:body).new("---\n- email: \"\e]2;nyan\a\"\n handle: handle\n id: id\n") + end + def command.with_response(response) + yield response + end + command.should_receive(:say).with("Owners for gem: name") + command.should_receive(:say).with("- .]2;nyan.") + command.show_owners "name" end - def command.with_response(response) - yield response - end - command.should_receive(:say).with("Owners for gem: name") - command.should_receive(:say).with("- .]2;nyan.") - command.show_owners "name" end end -- cgit v1.2.3