mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to ruby/spec@4eec3dc
This commit is contained in:
parent
ab8345271e
commit
1243255c3a
174 changed files with 1780 additions and 426 deletions
|
@ -88,6 +88,14 @@ Array.should have_method(:new)
|
|||
raise "oops"
|
||||
}.should raise_error(RuntimeError, /oops/)
|
||||
|
||||
-> {
|
||||
raise "oops"
|
||||
}.should raise_error(RuntimeError) { |e|
|
||||
# Custom checks on the Exception object
|
||||
e.message.should include("oops")
|
||||
e.cause.should == nil
|
||||
}
|
||||
|
||||
# To avoid! Instead, use an expectation testing what the code in the lambda does.
|
||||
# If an exception is raised, it will fail the example anyway.
|
||||
-> { ... }.should_not raise_error
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# The Ruby Spec Suite
|
||||
|
||||
[](https://travis-ci.org/ruby/spec)
|
||||
[](https://ci.appveyor.com/project/eregon/spec-x948i)
|
||||
[](https://github.com/ruby/spec/actions)
|
||||
[](https://github.com/ruby/spec/actions)
|
||||
[](https://gitter.im/ruby/spec)
|
||||
|
||||
The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language.
|
||||
|
|
|
@ -30,4 +30,22 @@ describe "Array#drop" do
|
|||
ary.shift
|
||||
ary.drop(1).should == [2]
|
||||
end
|
||||
|
||||
it "tries to convert the passed argument to an Integer using #to_int" do
|
||||
obj = mock("to_int")
|
||||
obj.should_receive(:to_int).and_return(2)
|
||||
|
||||
[1, 2, 3].drop(obj).should == [3]
|
||||
end
|
||||
|
||||
it "raises a TypeError when the passed argument can't be coerced to Integer" do
|
||||
-> { [1, 2].drop("cat") }.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it "raises a TypeError when the passed argument isn't an integer and #to_int returns non-Integer" do
|
||||
obj = mock("to_int")
|
||||
obj.should_receive(:to_int).and_return("cat")
|
||||
|
||||
-> { [1, 2].drop(obj) }.should raise_error(TypeError)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
|
||||
describe "Class#to_s" do
|
||||
it 'regular class returns same name as Module#to_s' do
|
||||
String.to_s.should == 'String'
|
||||
end
|
||||
|
||||
describe 'singleton class' do
|
||||
it 'for modules includes module name' do
|
||||
CoreClassSpecs.singleton_class.to_s.should == '#<Class:CoreClassSpecs>'
|
||||
end
|
||||
|
||||
it 'for classes includes class name' do
|
||||
CoreClassSpecs::Record.singleton_class.to_s.should == '#<Class:CoreClassSpecs::Record>'
|
||||
end
|
||||
|
||||
it 'for objects includes class name and object ID' do
|
||||
obj = CoreClassSpecs::Record.new
|
||||
obj.singleton_class.to_s.should =~ /#<Class:#<CoreClassSpecs::Record:0x[0-9a-f]+>>/
|
||||
end
|
||||
end
|
||||
end
|
15
spec/ruby/core/data/constants_spec.rb
Normal file
15
spec/ruby/core/data/constants_spec.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Data" do
|
||||
it "is a subclass of Object" do
|
||||
suppress_warning do
|
||||
Data.superclass.should == Object
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.5" do
|
||||
it "is deprecated" do
|
||||
-> { Data }.should complain(/constant ::Data is deprecated/)
|
||||
end
|
||||
end
|
||||
end
|
2
spec/ruby/core/env/assoc_spec.rb
vendored
2
spec/ruby/core/env/assoc_spec.rb
vendored
|
@ -26,6 +26,6 @@ describe "ENV.assoc" do
|
|||
end
|
||||
|
||||
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
|
||||
-> { ENV.assoc(Object.new) }.should raise_error(TypeError)
|
||||
-> { ENV.assoc(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
end
|
||||
|
|
6
spec/ruby/core/env/delete_spec.rb
vendored
6
spec/ruby/core/env/delete_spec.rb
vendored
|
@ -30,6 +30,12 @@ describe "ENV.delete" do
|
|||
ScratchPad.recorded.should == "foo"
|
||||
end
|
||||
|
||||
it "does not evaluate the block if the envirionment variable exists" do
|
||||
ENV["foo"] = "bar"
|
||||
ENV.delete("foo") { |name| fail "Should not happen" }
|
||||
ENV["foo"].should == nil
|
||||
end
|
||||
|
||||
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
|
||||
-> { ENV.delete(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
|
|
2
spec/ruby/core/env/each_key_spec.rb
vendored
2
spec/ruby/core/env/each_key_spec.rb
vendored
|
@ -10,7 +10,7 @@ describe "ENV.each_key" do
|
|||
ENV.clear
|
||||
ENV["1"] = "3"
|
||||
ENV["2"] = "4"
|
||||
ENV.each_key { |k| e << k }
|
||||
ENV.each_key { |k| e << k }.should equal(ENV)
|
||||
e.should include("1")
|
||||
e.should include("2")
|
||||
ensure
|
||||
|
|
2
spec/ruby/core/env/each_value_spec.rb
vendored
2
spec/ruby/core/env/each_value_spec.rb
vendored
|
@ -10,7 +10,7 @@ describe "ENV.each_value" do
|
|||
ENV.clear
|
||||
ENV["1"] = "3"
|
||||
ENV["2"] = "4"
|
||||
ENV.each_value { |v| e << v }
|
||||
ENV.each_value { |v| e << v }.should equal(ENV)
|
||||
e.should include("3")
|
||||
e.should include("4")
|
||||
ensure
|
||||
|
|
6
spec/ruby/core/env/index_spec.rb
vendored
6
spec/ruby/core/env/index_spec.rb
vendored
|
@ -3,4 +3,10 @@ require_relative 'shared/key'
|
|||
|
||||
describe "ENV.index" do
|
||||
it_behaves_like :env_key, :index
|
||||
|
||||
it "warns about deprecation" do
|
||||
-> do
|
||||
ENV.index("foo")
|
||||
end.should complain(/warning: ENV.index is deprecated; use ENV.key/)
|
||||
end
|
||||
end
|
||||
|
|
4
spec/ruby/core/env/keys_spec.rb
vendored
4
spec/ruby/core/env/keys_spec.rb
vendored
|
@ -2,8 +2,8 @@ require_relative '../../spec_helper'
|
|||
|
||||
describe "ENV.keys" do
|
||||
|
||||
it "returns all the keys" do
|
||||
ENV.keys.sort.should == ENV.to_hash.keys.sort
|
||||
it "returns an array of the keys" do
|
||||
ENV.keys.should == ENV.to_hash.keys
|
||||
end
|
||||
|
||||
it "returns the keys in the locale encoding" do
|
||||
|
|
6
spec/ruby/core/env/rehash_spec.rb
vendored
6
spec/ruby/core/env/rehash_spec.rb
vendored
|
@ -1 +1,7 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "ENV.rehash" do
|
||||
it "returns nil" do
|
||||
ENV.rehash.should == nil
|
||||
end
|
||||
end
|
||||
|
|
54
spec/ruby/core/env/replace_spec.rb
vendored
54
spec/ruby/core/env/replace_spec.rb
vendored
|
@ -1,15 +1,51 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "ENV.replace" do
|
||||
|
||||
it "replaces ENV with a Hash" do
|
||||
ENV["foo"] = "bar"
|
||||
e = ENV.reject { |k, v| k == "foo" }
|
||||
e["baz"] = "bam"
|
||||
ENV.replace e
|
||||
ENV["foo"].should == nil
|
||||
ENV["baz"].should == "bam"
|
||||
ENV.delete "baz"
|
||||
before :each do
|
||||
@orig = ENV.to_hash
|
||||
ENV.delete("foo")
|
||||
end
|
||||
|
||||
after :each do
|
||||
ENV.replace(@orig)
|
||||
end
|
||||
|
||||
it "replaces ENV with a Hash" do
|
||||
ENV.replace("foo" => "0", "bar" => "1").should equal(ENV)
|
||||
ENV.size.should == 2
|
||||
ENV["foo"].should == "0"
|
||||
ENV["bar"].should == "1"
|
||||
end
|
||||
|
||||
it "raises TypeError if the argument is not a Hash" do
|
||||
-> { ENV.replace(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into Hash")
|
||||
ENV.to_hash.should == @orig
|
||||
end
|
||||
|
||||
it "raises TypeError if a key is not a String" do
|
||||
-> { ENV.replace(Object.new => "0") }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
ENV.to_hash.should == @orig
|
||||
end
|
||||
|
||||
it "raises TypeError if a value is not a String" do
|
||||
-> { ENV.replace("foo" => Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
ENV.to_hash.should == @orig
|
||||
end
|
||||
|
||||
it "raises Errno::EINVAL when the key contains the '=' character" do
|
||||
-> { ENV.replace("foo=" =>"bar") }.should raise_error(Errno::EINVAL)
|
||||
end
|
||||
|
||||
it "raises Errno::EINVAL when the key is an empty string" do
|
||||
-> { ENV.replace("" => "bar") }.should raise_error(Errno::EINVAL)
|
||||
end
|
||||
|
||||
it "does not accept good data preceding an error" do
|
||||
-> { ENV.replace("foo" => "1", Object.new => Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
|
||||
it "does not accept good data following an error" do
|
||||
-> { ENV.replace(Object.new => Object.new, "foo" => "0") }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
ENV.to_hash.should == @orig
|
||||
end
|
||||
end
|
||||
|
|
13
spec/ruby/core/env/shared/to_hash.rb
vendored
13
spec/ruby/core/env/shared/to_hash.rb
vendored
|
@ -1,10 +1,17 @@
|
|||
describe :env_to_hash, shared: true do
|
||||
before :each do
|
||||
@saved_foo = ENV["foo"]
|
||||
end
|
||||
|
||||
after :each do
|
||||
ENV["foo"]= @saved_foo
|
||||
end
|
||||
|
||||
it "returns the ENV as a hash" do
|
||||
ENV["foo"] = "bar"
|
||||
h = ENV.send(@method)
|
||||
h.should be_an_instance_of(Hash)
|
||||
h["foo"].should == "bar"
|
||||
ENV.delete "foo"
|
||||
end
|
||||
|
||||
it "uses the locale encoding for keys" do
|
||||
|
@ -18,5 +25,9 @@ describe :env_to_hash, shared: true do
|
|||
it "duplicates the ENV when converting to a Hash" do
|
||||
h = ENV.send(@method)
|
||||
h.should_not equal ENV
|
||||
h.size.should == ENV.size
|
||||
h.each_pair do |k, v|
|
||||
ENV[k].should == v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
44
spec/ruby/core/env/shared/update.rb
vendored
44
spec/ruby/core/env/shared/update.rb
vendored
|
@ -9,8 +9,8 @@ describe :env_update, shared: true do
|
|||
ENV["bar"] = @saved_bar
|
||||
end
|
||||
|
||||
it "adds the parameter hash to ENV" do
|
||||
ENV.send @method, {"foo" => "0", "bar" => "1"}
|
||||
it "adds the parameter hash to ENV, returning ENV" do
|
||||
ENV.send(@method, "foo" => "0", "bar" => "1").should equal(ENV)
|
||||
ENV["foo"].should == "0"
|
||||
ENV["bar"].should == "1"
|
||||
end
|
||||
|
@ -19,17 +19,43 @@ describe :env_update, shared: true do
|
|||
ENV.send(@method, {"foo" => "0", "bar" => "1"}).should equal(ENV)
|
||||
end
|
||||
|
||||
it "yields key, the old value and the new value when replacing entries" do
|
||||
it "yields key, the old value and the new value when replacing an entry" do
|
||||
ENV.send @method, {"foo" => "0", "bar" => "3"}
|
||||
a = []
|
||||
ENV.send @method, {"foo" => "1", "bar" => "4"} do |key, old, new|
|
||||
a << [key, old, new]
|
||||
new
|
||||
end
|
||||
a[0].should == ["foo", "0", "1"]
|
||||
a[1].should == ["bar", "3", "4"]
|
||||
end
|
||||
|
||||
it "yields key, the old value and the new value when replacing an entry" do
|
||||
ENV.send @method, {"foo" => "0", "bar" => "3"}
|
||||
ENV.send @method, {"foo" => "1", "bar" => "4"} do |key, old, new|
|
||||
(new.to_i + 1).to_s
|
||||
end
|
||||
ENV["foo"].should == "2"
|
||||
ENV["bar"].should == "5"
|
||||
a[0].should == ["foo", "0", "1"]
|
||||
a[1].should == ["bar", "3", "4"]
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
# BUG: https://bugs.ruby-lang.org/issues/16192
|
||||
it "does not evaluate the block when the name is new" do
|
||||
ENV.delete("bar")
|
||||
ENV.send @method, {"foo" => "0"}
|
||||
ENV.send(@method, "bar" => "1") { |key, old, new| fail "Should not get here" }
|
||||
ENV["bar"].should == "1"
|
||||
end
|
||||
|
||||
# BUG: https://bugs.ruby-lang.org/issues/16192
|
||||
it "does not use the block's return value as the value when the name is new" do
|
||||
ENV.delete("bar")
|
||||
ENV.send @method, {"foo" => "0"}
|
||||
ENV.send(@method, "bar" => "1") { |key, old, new| "Should not use this value" }
|
||||
ENV["foo"].should == "0"
|
||||
ENV["bar"].should == "1"
|
||||
end
|
||||
end
|
||||
|
||||
it "returns ENV when block given" do
|
||||
|
@ -44,6 +70,14 @@ describe :env_update, shared: true do
|
|||
-> { ENV.send @method, "foo" => Object.new }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
|
||||
it "raises Errno::EINVAL when a name contains the '=' character" do
|
||||
-> { ENV.send(@method, "foo=" => "bar") }.should raise_error(Errno::EINVAL)
|
||||
end
|
||||
|
||||
it "raises Errno::EINVAL when a name is an empty string" do
|
||||
-> { ENV.send(@method, "" => "bar") }.should raise_error(Errno::EINVAL)
|
||||
end
|
||||
|
||||
it "updates good data preceding an error" do
|
||||
ENV["foo"] = "0"
|
||||
begin
|
||||
|
|
5
spec/ruby/core/env/to_a_spec.rb
vendored
5
spec/ruby/core/env/to_a_spec.rb
vendored
|
@ -3,11 +3,10 @@ require_relative '../../spec_helper'
|
|||
describe "ENV.to_a" do
|
||||
|
||||
it "returns the ENV as an array" do
|
||||
ENV["foo"] = "bar"
|
||||
a = ENV.to_a
|
||||
a.is_a?(Array).should == true
|
||||
a.find { |e| e.first == "foo" }.should == ["foo", "bar"]
|
||||
ENV.delete "foo"
|
||||
a.size.should == ENV.size
|
||||
ENV.each_pair { |k, v| a.should include([k, v])}
|
||||
end
|
||||
|
||||
it "returns the entries in the locale encoding" do
|
||||
|
|
5
spec/ruby/core/env/to_h_spec.rb
vendored
5
spec/ruby/core/env/to_h_spec.rb
vendored
|
@ -19,6 +19,11 @@ describe "ENV.to_h" do
|
|||
ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" }
|
||||
end
|
||||
|
||||
it "does not require the array elements to be strings" do
|
||||
ENV.replace("a" => "b", "c" => "d")
|
||||
ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d }
|
||||
end
|
||||
|
||||
it "raises ArgumentError if block returns longer or shorter array" do
|
||||
-> do
|
||||
ENV.to_h { |k, v| [k, v.upcase, 1] }
|
||||
|
|
28
spec/ruby/core/env/values_at_spec.rb
vendored
28
spec/ruby/core/env/values_at_spec.rb
vendored
|
@ -1,17 +1,37 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "ENV.values_at" do
|
||||
before :each do
|
||||
@saved_foo = ENV["foo"]
|
||||
@saved_bar = ENV["bar"]
|
||||
end
|
||||
|
||||
it "returns an array of the values referenced by the parameters as keys" do
|
||||
after :each do
|
||||
ENV["foo"] = @saved_foo
|
||||
ENV["bar"] = @saved_bar
|
||||
end
|
||||
|
||||
it "returns an array of the values corresponding to the given keys" do
|
||||
ENV["foo"] = "oof"
|
||||
ENV["bar"] = "rab"
|
||||
ENV.values_at.should == []
|
||||
ENV.values_at("bar", "foo").should == ["rab", "oof"]
|
||||
ENV.delete "foo"
|
||||
ENV.delete "bar"
|
||||
end
|
||||
|
||||
it "returns an empty array if no keys specified" do
|
||||
ENV.values_at.should == []
|
||||
end
|
||||
|
||||
it "returns nil for each key that is not a name" do
|
||||
ENV["foo"] = "oof"
|
||||
ENV["bar"] = "rab"
|
||||
ENV.values_at("x", "bar", "y", "foo", "z").should == [nil, "rab", nil, "oof", nil]
|
||||
end
|
||||
|
||||
it "uses the locale encoding" do
|
||||
ENV.values_at(ENV.keys.first).first.encoding.should == Encoding.find('locale')
|
||||
end
|
||||
|
||||
it "raises TypeError when a key is not coercible to String" do
|
||||
-> { ENV.values_at("foo", Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
end
|
||||
|
|
9
spec/ruby/core/env/values_spec.rb
vendored
9
spec/ruby/core/env/values_spec.rb
vendored
|
@ -3,14 +3,7 @@ require_relative '../../spec_helper'
|
|||
describe "ENV.values" do
|
||||
|
||||
it "returns an array of the values" do
|
||||
orig = ENV.to_hash
|
||||
begin
|
||||
ENV.replace "a" => "b", "c" => "d"
|
||||
a = ENV.values
|
||||
a.sort.should == ["b", "d"]
|
||||
ensure
|
||||
ENV.replace orig
|
||||
end
|
||||
ENV.values.should == ENV.to_hash.values
|
||||
end
|
||||
|
||||
it "uses the locale encoding" do
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "NoMethodError#args" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "ArgumentError" do
|
||||
it "is a subclass of StandardError" do
|
||||
StandardError.should be_ancestor_of(ArgumentError)
|
||||
end
|
||||
|
||||
it "gives its own class name as message if it has no message" do
|
||||
ArgumentError.new.message.should == "ArgumentError"
|
||||
end
|
||||
end
|
|
@ -47,7 +47,7 @@ describe "Exception#backtrace" do
|
|||
end
|
||||
end
|
||||
|
||||
it "produces a backtrace for an exception captured using $!" do
|
||||
it "captures the backtrace for an exception into $!" do
|
||||
exception = begin
|
||||
raise
|
||||
rescue RuntimeError
|
||||
|
@ -57,6 +57,16 @@ describe "Exception#backtrace" do
|
|||
exception.backtrace.first.should =~ /backtrace_spec/
|
||||
end
|
||||
|
||||
it "captures the backtrace for an exception into $@" do
|
||||
backtrace = begin
|
||||
raise
|
||||
rescue RuntimeError
|
||||
$@
|
||||
end
|
||||
|
||||
backtrace.first.should =~ /backtrace_spec/
|
||||
end
|
||||
|
||||
it "returns an Array that can be updated" do
|
||||
begin
|
||||
raise
|
||||
|
|
|
@ -1,5 +1,39 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "SystemCallError.===" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
before :all do
|
||||
@example_errno_class = Errno::EINVAL
|
||||
@example_errno = @example_errno_class::Errno
|
||||
end
|
||||
|
||||
it "returns true for an instance of the same class" do
|
||||
Errno::EINVAL.should === Errno::EINVAL.new
|
||||
end
|
||||
|
||||
it "returns true if errnos same" do
|
||||
e = SystemCallError.new('foo', @example_errno)
|
||||
@example_errno_class.===(e).should == true
|
||||
end
|
||||
|
||||
it "returns false if errnos different" do
|
||||
e = SystemCallError.new('foo', @example_errno + 1)
|
||||
@example_errno_class.===(e).should == false
|
||||
end
|
||||
|
||||
it "returns false if arg is not kind of SystemCallError" do
|
||||
e = Object.new
|
||||
@example_errno_class.===(e).should == false
|
||||
end
|
||||
|
||||
it "returns true if receiver is generic and arg is kind of SystemCallError" do
|
||||
unknown_error_number = Errno.constants.size
|
||||
e = SystemCallError.new('foo', @example_errno)
|
||||
SystemCallError.===(e).should == true
|
||||
end
|
||||
|
||||
it "returns false if receiver is generic and arg is not kind of SystemCallError" do
|
||||
unknown_error_number = Errno.constants.size
|
||||
e = Object.new
|
||||
SystemCallError.===(e).should == false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Encoding::UndefinedConversionError#destination_encoding_name" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the destination encoding name" do
|
||||
ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::UndefinedConversionError => e
|
||||
e.destination_encoding_name.should == "EUC-JP"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Encoding::InvalidByteSequenceError#destination_encoding_name" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the destination encoding name" do
|
||||
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::InvalidByteSequenceError => e
|
||||
e.destination_encoding_name.should == "UTF-8"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Encoding::UndefinedConversionError#destination_encoding" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the destination encoding" do
|
||||
ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::UndefinedConversionError => e
|
||||
e.destination_encoding.should == Encoding::EUC_JP
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Encoding::InvalidByteSequenceError#destination_encoding" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the destination encoding" do
|
||||
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::InvalidByteSequenceError => e
|
||||
e.destination_encoding.should == Encoding::UTF_8
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Encoding::InvalidByteSequenceError#error_bytes" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the error bytes" do
|
||||
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::InvalidByteSequenceError => e
|
||||
e.error_bytes.should == "\xA0".force_encoding("ASCII-8BIT")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Encoding::UndefinedConversionError#error_char" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the error char" do
|
||||
ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::UndefinedConversionError => e
|
||||
e.error_char.should == "\u00A0"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,48 +6,6 @@ describe "Exception.exception" do
|
|||
it_behaves_like :exception_new, :exception
|
||||
end
|
||||
|
||||
describe "Exception" do
|
||||
it "is a Class" do
|
||||
Exception.should be_kind_of(Class)
|
||||
end
|
||||
|
||||
it "is a superclass of NoMemoryError" do
|
||||
Exception.should be_ancestor_of(NoMemoryError)
|
||||
end
|
||||
|
||||
it "is a superclass of ScriptError" do
|
||||
Exception.should be_ancestor_of(ScriptError)
|
||||
end
|
||||
|
||||
it "is a superclass of SignalException" do
|
||||
Exception.should be_ancestor_of(SignalException)
|
||||
end
|
||||
|
||||
it "is a superclass of Interrupt" do
|
||||
SignalException.should be_ancestor_of(Interrupt)
|
||||
end
|
||||
|
||||
it "is a superclass of StandardError" do
|
||||
Exception.should be_ancestor_of(StandardError)
|
||||
end
|
||||
|
||||
it "is a superclass of SystemExit" do
|
||||
Exception.should be_ancestor_of(SystemExit)
|
||||
end
|
||||
|
||||
it "is a superclass of SystemStackError" do
|
||||
Exception.should be_ancestor_of(SystemStackError)
|
||||
end
|
||||
|
||||
it "is a superclass of SecurityError" do
|
||||
Exception.should be_ancestor_of(SecurityError)
|
||||
end
|
||||
|
||||
it "is a superclass of EncodingError" do
|
||||
Exception.should be_ancestor_of(EncodingError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Exception#exception" do
|
||||
it "returns self when passed no argument" do
|
||||
e = RuntimeError.new
|
||||
|
@ -82,6 +40,18 @@ describe "Exception#exception" do
|
|||
raised_second.should == caught_second
|
||||
end
|
||||
|
||||
it "captures an exception into $!" do
|
||||
exception = begin
|
||||
raise
|
||||
rescue RuntimeError
|
||||
$!
|
||||
end
|
||||
|
||||
exception.class.should == RuntimeError
|
||||
exception.message.should == ""
|
||||
exception.backtrace.first.should =~ /exception_spec/
|
||||
end
|
||||
|
||||
class CustomArgumentError < StandardError
|
||||
attr_reader :val
|
||||
def initialize(val)
|
||||
|
|
62
spec/ruby/core/exception/hierarchy_spec.rb
Normal file
62
spec/ruby/core/exception/hierarchy_spec.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Exception" do
|
||||
it "has the right class hierarchy" do
|
||||
hierarchy = {
|
||||
Exception => {
|
||||
NoMemoryError => nil,
|
||||
ScriptError => {
|
||||
LoadError => nil,
|
||||
NotImplementedError => nil,
|
||||
SyntaxError => nil,
|
||||
},
|
||||
SecurityError => nil,
|
||||
SignalException => {
|
||||
Interrupt => nil,
|
||||
},
|
||||
StandardError => {
|
||||
ArgumentError => {
|
||||
UncaughtThrowError => nil,
|
||||
},
|
||||
EncodingError => nil,
|
||||
FiberError => nil,
|
||||
IOError => {
|
||||
EOFError => nil,
|
||||
},
|
||||
IndexError => {
|
||||
KeyError => nil,
|
||||
StopIteration => {
|
||||
ClosedQueueError => nil,
|
||||
},
|
||||
},
|
||||
LocalJumpError => nil,
|
||||
NameError => {
|
||||
NoMethodError => nil,
|
||||
},
|
||||
RangeError => {
|
||||
FloatDomainError => nil,
|
||||
},
|
||||
RegexpError => nil,
|
||||
RuntimeError => nil,
|
||||
SystemCallError => nil,
|
||||
ThreadError => nil,
|
||||
TypeError => nil,
|
||||
ZeroDivisionError => nil,
|
||||
},
|
||||
SystemExit => nil,
|
||||
SystemStackError => nil,
|
||||
},
|
||||
}
|
||||
ruby_version_is "2.5" do
|
||||
hierarchy[Exception][StandardError][RuntimeError] = {FrozenError => nil}
|
||||
end
|
||||
traverse = -> parent_class, parent_subclass_hash {
|
||||
parent_subclass_hash.each do |child_class, child_subclass_hash|
|
||||
child_class.class.should == Class
|
||||
child_class.superclass.should == parent_class
|
||||
traverse.call(child_class, child_subclass_hash) if child_subclass_hash
|
||||
end
|
||||
}
|
||||
traverse.call(Object, hierarchy)
|
||||
end
|
||||
end
|
|
@ -1,11 +1,5 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Interrupt" do
|
||||
it "is a subclass of SignalException" do
|
||||
Interrupt.superclass.should == SignalException
|
||||
end
|
||||
end
|
||||
|
||||
describe "Interrupt.new" do
|
||||
it "returns an instance of interrupt with no message given" do
|
||||
e = Interrupt.new
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Encoding::InvalidByteSequenceError#readagain_bytes" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the next byte" do
|
||||
begin
|
||||
"abc\xa4def".encode("ISO-8859-1", "EUC-JP")
|
||||
rescue Encoding::InvalidByteSequenceError => e
|
||||
e.error_bytes.should == "\xA4".force_encoding("ASCII-8BIT")
|
||||
e.readagain_bytes.should == 'd'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "ScriptError" do
|
||||
it "is a superclass of LoadError" do
|
||||
ScriptError.should be_ancestor_of(LoadError)
|
||||
end
|
||||
|
||||
it "is a superclass of NotImplementedError" do
|
||||
ScriptError.should be_ancestor_of(NotImplementedError)
|
||||
end
|
||||
|
||||
it "is a superclass of SyntaxError" do
|
||||
ScriptError.should be_ancestor_of(SyntaxError)
|
||||
end
|
||||
end
|
|
@ -30,6 +30,12 @@ describe "SignalException.new" do
|
|||
-> { SignalException.new("NONEXISTENT") }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
ruby_version_is "2.6" do
|
||||
it "raises an exception with an invalid first argument type" do
|
||||
-> { SignalException.new(Object.new) }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
it "takes a signal symbol without SIG prefix as the first argument" do
|
||||
exc = SignalException.new(:INT)
|
||||
exc.signo.should == Signal.list["INT"]
|
||||
|
@ -72,3 +78,48 @@ describe "rescuing SignalException" do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "SignalException" do
|
||||
it "can be rescued" do
|
||||
ruby_exe(<<-RUBY)
|
||||
begin
|
||||
raise SignalException, 'SIGKILL'
|
||||
rescue SignalException
|
||||
exit(0)
|
||||
end
|
||||
exit(1)
|
||||
RUBY
|
||||
|
||||
$?.exitstatus.should == 0
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
it "runs after at_exit" do
|
||||
output = ruby_exe(<<-RUBY)
|
||||
at_exit do
|
||||
puts "hello"
|
||||
$stdout.flush
|
||||
end
|
||||
|
||||
raise SignalException, 'SIGKILL'
|
||||
RUBY
|
||||
|
||||
$?.termsig.should == Signal.list.fetch("KILL")
|
||||
output.should == "hello\n"
|
||||
end
|
||||
|
||||
it "cannot be trapped with Signal.trap" do
|
||||
ruby_exe(<<-RUBY)
|
||||
Signal.trap("PROF") {}
|
||||
raise(SignalException, "PROF")
|
||||
RUBY
|
||||
|
||||
$?.termsig.should == Signal.list.fetch("PROF")
|
||||
end
|
||||
|
||||
it "self-signals for USR1" do
|
||||
ruby_exe("raise(SignalException, 'USR1')")
|
||||
$?.termsig.should == Signal.list.fetch('USR1')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Encoding::UndefinedConversionError#source_encoding_name" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the source encoding name" do
|
||||
ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::UndefinedConversionError => e
|
||||
e.source_encoding_name.should == "UTF-8"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Encoding::InvalidByteSequenceError#source_encoding_name" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the source encoding name" do
|
||||
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::InvalidByteSequenceError => e
|
||||
e.source_encoding_name.should == "EUC-JP"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Encoding::UndefinedConversionError#source_encoding" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the source encoding" do
|
||||
ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::UndefinedConversionError => e
|
||||
e.source_encoding.should == Encoding::UTF_8
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Encoding::InvalidByteSequenceError#source_encoding" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns the source encoding" do
|
||||
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
|
||||
begin
|
||||
ec.convert("\xa0")
|
||||
rescue Encoding::InvalidByteSequenceError => e
|
||||
e.source_encoding.should == Encoding::EUC_JP
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,56 +1,23 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "StandardError" do
|
||||
it "is a superclass of ArgumentError" do
|
||||
StandardError.should be_ancestor_of(ArgumentError)
|
||||
end
|
||||
|
||||
it "is a superclass of IOError" do
|
||||
StandardError.should be_ancestor_of(IOError)
|
||||
end
|
||||
|
||||
it "is a superclass of IndexError" do
|
||||
StandardError.should be_ancestor_of(IndexError)
|
||||
end
|
||||
|
||||
it "is a superclass of LocalJumpError" do
|
||||
StandardError.should be_ancestor_of(LocalJumpError)
|
||||
end
|
||||
|
||||
it "is a superclass of NameError" do
|
||||
StandardError.should be_ancestor_of(NameError)
|
||||
end
|
||||
|
||||
it "is a superclass of RangeError" do
|
||||
StandardError.should be_ancestor_of(RangeError)
|
||||
end
|
||||
|
||||
it "is a superclass of RegexpError" do
|
||||
StandardError.should be_ancestor_of(RegexpError)
|
||||
end
|
||||
|
||||
it "is a superclass of RuntimeError" do
|
||||
StandardError.should be_ancestor_of(RuntimeError)
|
||||
end
|
||||
|
||||
it "is a superclass of SystemCallError" do
|
||||
StandardError.should be_ancestor_of(SystemCallError.new("").class)
|
||||
end
|
||||
it "is a superclass of ThreadError" do
|
||||
StandardError.should be_ancestor_of(ThreadError)
|
||||
end
|
||||
|
||||
it "is a superclass of TypeError" do
|
||||
StandardError.should be_ancestor_of(TypeError)
|
||||
end
|
||||
|
||||
it "is a superclass of ZeroDivisionError" do
|
||||
StandardError.should be_ancestor_of(ZeroDivisionError)
|
||||
end
|
||||
|
||||
ruby_version_is '2.5' do
|
||||
it "is a superclass of FrozenError" do
|
||||
StandardError.should be_ancestor_of(FrozenError)
|
||||
it "rescues StandardError" do
|
||||
begin
|
||||
raise StandardError
|
||||
rescue => exception
|
||||
exception.class.should == StandardError
|
||||
end
|
||||
end
|
||||
|
||||
it "rescues subclass of StandardError" do
|
||||
begin
|
||||
raise RuntimeError
|
||||
rescue => exception
|
||||
exception.class.should == RuntimeError
|
||||
end
|
||||
end
|
||||
|
||||
it "does not rescue superclass of StandardError" do
|
||||
-> { begin; raise Exception; rescue; end }.should raise_error(Exception)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,41 +20,82 @@ describe "SystemCallError" do
|
|||
end
|
||||
|
||||
describe "SystemCallError.new" do
|
||||
before :all do
|
||||
@example_errno = Errno::EINVAL::Errno
|
||||
@example_errno_class = Errno::EINVAL
|
||||
@last_known_errno = Errno.constants.size - 1
|
||||
@unknown_errno = Errno.constants.size
|
||||
end
|
||||
|
||||
it "requires at least one argument" do
|
||||
-> { SystemCallError.new }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "accepts single Fixnum argument as errno" do
|
||||
SystemCallError.new(-2**24).errno.should == -2**24
|
||||
SystemCallError.new(42).errno.should == 42
|
||||
SystemCallError.new(-1).errno.should == -1
|
||||
SystemCallError.new(0).errno.should == 0
|
||||
SystemCallError.new(@last_known_errno).errno.should == @last_known_errno
|
||||
SystemCallError.new(@unknown_errno).errno.should == @unknown_errno
|
||||
SystemCallError.new(2**24).errno.should == 2**24
|
||||
end
|
||||
|
||||
it "constructs a SystemCallError for an unknown error number" do
|
||||
SystemCallError.new(-2**24).should be_an_instance_of(SystemCallError)
|
||||
SystemCallError.new(-1).should be_an_instance_of(SystemCallError)
|
||||
SystemCallError.new(@unknown_errno).should be_an_instance_of(SystemCallError)
|
||||
SystemCallError.new(2**24).should be_an_instance_of(SystemCallError)
|
||||
end
|
||||
|
||||
it "constructs the appropriate Errno class" do
|
||||
# EINVAL should be more or less mortable across the platforms,
|
||||
# so let's use it then.
|
||||
SystemCallError.new(22).should be_kind_of(SystemCallError)
|
||||
SystemCallError.new(22).should be_an_instance_of(Errno::EINVAL)
|
||||
SystemCallError.new(2**28).should be_an_instance_of(SystemCallError)
|
||||
e = SystemCallError.new(@example_errno)
|
||||
e.should be_kind_of(SystemCallError)
|
||||
e.should be_an_instance_of(@example_errno_class)
|
||||
end
|
||||
|
||||
it "accepts an optional custom message preceding the errno" do
|
||||
exc = SystemCallError.new("custom message", 22)
|
||||
exc.should be_an_instance_of(Errno::EINVAL)
|
||||
exc.errno.should == 22
|
||||
exc.message.should == "Invalid argument - custom message"
|
||||
exc = SystemCallError.new("custom message", @example_errno)
|
||||
exc.should be_an_instance_of(@example_errno_class)
|
||||
exc.errno.should == @example_errno
|
||||
exc.message.should == 'Invalid argument - custom message'
|
||||
end
|
||||
|
||||
it "accepts an optional third argument specifying the location" do
|
||||
exc = SystemCallError.new("custom message", 22, "location")
|
||||
exc.should be_an_instance_of(Errno::EINVAL)
|
||||
exc.errno.should == 22
|
||||
exc.message.should == "Invalid argument @ location - custom message"
|
||||
exc = SystemCallError.new("custom message", @example_errno, "location")
|
||||
exc.should be_an_instance_of(@example_errno_class)
|
||||
exc.errno.should == @example_errno
|
||||
exc.message.should == 'Invalid argument @ location - custom message'
|
||||
end
|
||||
|
||||
it "coerces location if it is not a String" do
|
||||
e = SystemCallError.new('foo', 1, :not_a_string)
|
||||
e.message.should =~ /@ not_a_string - foo/
|
||||
end
|
||||
|
||||
it "returns an arity of -1 for the initialize method" do
|
||||
SystemCallError.instance_method(:initialize).arity.should == -1
|
||||
end
|
||||
|
||||
it "converts to Integer if errno is a Float" do
|
||||
SystemCallError.new('foo', 2.0).should == SystemCallError.new('foo', 2)
|
||||
SystemCallError.new('foo', 2.9).should == SystemCallError.new('foo', 2)
|
||||
end
|
||||
|
||||
it "converts to Integer if errno is a Complex convertible to Integer" do
|
||||
SystemCallError.new('foo', Complex(2.9, 0)).should == SystemCallError.new('foo', 2)
|
||||
end
|
||||
|
||||
it "raises TypeError if message is not a String" do
|
||||
-> { SystemCallError.new(:foo, 1) }.should raise_error(TypeError, /no implicit conversion of Symbol into String/)
|
||||
end
|
||||
|
||||
it "raises TypeError if errno is not an Integer" do
|
||||
-> { SystemCallError.new('foo', 'bar') }.should raise_error(TypeError, /no implicit conversion of String into Integer/)
|
||||
end
|
||||
|
||||
it "raises RangeError if errno is a Complex not convertible to Integer" do
|
||||
-> { SystemCallError.new('foo', Complex(2.9, 1)) }.should raise_error(RangeError, /can't convert/)
|
||||
end
|
||||
end
|
||||
|
||||
describe "SystemCallError#errno" do
|
||||
|
|
|
@ -19,5 +19,19 @@ describe "Exception#to_s" do
|
|||
end
|
||||
|
||||
describe "NameError#to_s" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "raises its own message for an undefined variable" do
|
||||
begin
|
||||
puts not_defined
|
||||
rescue => exception
|
||||
exception.message.should =~ /undefined local variable or method `not_defined'/
|
||||
end
|
||||
end
|
||||
|
||||
it "raises its own message for an undefined constant" do
|
||||
begin
|
||||
puts NotDefined
|
||||
rescue => exception
|
||||
exception.message.should =~ /uninitialized constant NotDefined/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,8 +12,9 @@ describe "File.ftype" do
|
|||
end
|
||||
|
||||
it "raises Errno::ENOENT if the file is not valid" do
|
||||
l = -> { File.ftype("/#{$$}#{Time.now.to_f}") }
|
||||
l.should raise_error(Errno::ENOENT)
|
||||
-> {
|
||||
File.ftype("/#{$$}#{Time.now.to_f}")
|
||||
}.should raise_error(Errno::ENOENT)
|
||||
end
|
||||
|
||||
it "returns a String" do
|
||||
|
|
40
spec/ruby/core/file/lutime_spec.rb
Normal file
40
spec/ruby/core/file/lutime_spec.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
ruby_version_is "2.5" do
|
||||
describe "File.lutime" do
|
||||
platform_is_not :windows do
|
||||
before :each do
|
||||
@atime = Time.utc(2000)
|
||||
@mtime = Time.utc(2001)
|
||||
@file = tmp("specs_lutime_file")
|
||||
@symlink = tmp("specs_lutime_symlink")
|
||||
touch @file
|
||||
File.symlink(@file, @symlink)
|
||||
end
|
||||
|
||||
after :each do
|
||||
rm_r @file, @symlink
|
||||
end
|
||||
|
||||
it "sets the access and modification time for a regular file" do
|
||||
File.lutime(@atime, @mtime, @file)
|
||||
stat = File.stat(@file)
|
||||
stat.atime.should == @atime
|
||||
stat.mtime.should === @mtime
|
||||
end
|
||||
|
||||
it "sets the access and modification time for a symlink" do
|
||||
original = File.stat(@file)
|
||||
|
||||
File.lutime(@atime, @mtime, @symlink)
|
||||
stat = File.lstat(@symlink)
|
||||
stat.atime.should == @atime
|
||||
stat.mtime.should === @mtime
|
||||
|
||||
file = File.stat(@file)
|
||||
file.atime.should == original.atime
|
||||
file.mtime.should == original.mtime
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -623,6 +623,14 @@ describe "File.open" do
|
|||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.5" do
|
||||
it "raises ArgumentError if mixing :newline and binary mode" do
|
||||
-> {
|
||||
File.open(@file, "rb", newline: :universal) {}
|
||||
}.should raise_error(ArgumentError, "newline decorator with binary mode")
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.6" do
|
||||
context "'x' flag" do
|
||||
before :each do
|
||||
|
|
|
@ -16,6 +16,38 @@ describe "Float#<=>" do
|
|||
(1.0 <=> "1").should be_nil
|
||||
end
|
||||
|
||||
it "compares using #coerce when argument is not a Float" do
|
||||
klass = Class.new do
|
||||
attr_reader :call_count
|
||||
def coerce(other)
|
||||
@call_count ||= 0
|
||||
@call_count += 1
|
||||
[other, 42.0]
|
||||
end
|
||||
end
|
||||
|
||||
coercible = klass.new
|
||||
(2.33 <=> coercible).should == -1
|
||||
(42.0 <=> coercible).should == 0
|
||||
(43.0 <=> coercible).should == 1
|
||||
coercible.call_count.should == 3
|
||||
end
|
||||
|
||||
ruby_version_is "2.5" do
|
||||
it "raises TypeError when #coerce misbehaves" do
|
||||
klass = Class.new do
|
||||
def coerce(other)
|
||||
:incorrect
|
||||
end
|
||||
end
|
||||
|
||||
bad_coercible = klass.new
|
||||
-> {
|
||||
4.2 <=> bad_coercible
|
||||
}.should raise_error(TypeError, "coerce must return [x, y]")
|
||||
end
|
||||
end
|
||||
|
||||
# The 4 tests below are taken from matz's revision 23730 for Ruby trunk
|
||||
#
|
||||
it "returns 1 when self is Infinity and other is a Bignum" do
|
||||
|
|
25
spec/ruby/core/integer/constants_spec.rb
Normal file
25
spec/ruby/core/integer/constants_spec.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "Fixnum" do
|
||||
it "is unified into Integer" do
|
||||
suppress_warning do
|
||||
Fixnum.should equal(Integer)
|
||||
end
|
||||
end
|
||||
|
||||
it "is deprecated" do
|
||||
-> { Fixnum }.should complain(/constant ::Fixnum is deprecated/)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Bignum" do
|
||||
it "is unified into Integer" do
|
||||
suppress_warning do
|
||||
Bignum.should equal(Integer)
|
||||
end
|
||||
end
|
||||
|
||||
it "is deprecated" do
|
||||
-> { Bignum }.should complain(/constant ::Bignum is deprecated/)
|
||||
end
|
||||
end
|
|
@ -1,13 +1,22 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
require_relative '../process/fixtures/common'
|
||||
|
||||
describe "IO.popen" do
|
||||
ProcessSpecs.use_system_ruby(self)
|
||||
|
||||
before :each do
|
||||
@fname = tmp("IO_popen_spec")
|
||||
@io = nil
|
||||
@var = "$FOO"
|
||||
platform_is :windows do
|
||||
@var = "%FOO%"
|
||||
end
|
||||
end
|
||||
|
||||
after :each do
|
||||
@io.close if @io
|
||||
@io.close if @io and !@io.closed?
|
||||
rm_r @fname
|
||||
end
|
||||
|
||||
it "returns an open IO" do
|
||||
|
@ -16,27 +25,15 @@ describe "IO.popen" do
|
|||
end
|
||||
|
||||
it "reads a read-only pipe" do
|
||||
@io = IO.popen(ruby_cmd('puts "foo"'), "r")
|
||||
@io = IO.popen('echo foo', "r")
|
||||
@io.read.should == "foo\n"
|
||||
end
|
||||
|
||||
it "raises IOError when writing a read-only pipe" do
|
||||
@io = IO.popen(ruby_cmd('puts "foo"'), "r")
|
||||
@io = IO.popen('echo foo', "r")
|
||||
-> { @io.write('bar') }.should raise_error(IOError)
|
||||
@io.read.should == "foo\n"
|
||||
end
|
||||
end
|
||||
|
||||
describe "IO.popen" do
|
||||
before :each do
|
||||
@fname = tmp("IO_popen_spec")
|
||||
@io = nil
|
||||
end
|
||||
|
||||
after :each do
|
||||
@io.close if @io and !@io.closed?
|
||||
rm_r @fname
|
||||
end
|
||||
|
||||
it "sees an infinitely looping subprocess exit when read pipe is closed" do
|
||||
io = IO.popen ruby_cmd('r = loop{puts "y"; 0} rescue 1; exit r'), 'r'
|
||||
|
@ -97,16 +94,6 @@ describe "IO.popen" do
|
|||
mode.should_receive(:to_str).and_return("r")
|
||||
@io = IO.popen(ruby_cmd('exit 0'), mode)
|
||||
end
|
||||
end
|
||||
|
||||
describe "IO.popen" do
|
||||
before :each do
|
||||
@io = nil
|
||||
end
|
||||
|
||||
after :each do
|
||||
@io.close if @io
|
||||
end
|
||||
|
||||
describe "with a block" do
|
||||
it "yields an open IO to the block" do
|
||||
|
@ -171,13 +158,13 @@ describe "IO.popen" do
|
|||
|
||||
context "with a leading ENV Hash" do
|
||||
it "accepts a single String command" do
|
||||
IO.popen({"FOO" => "bar"}, ruby_cmd('puts ENV["FOO"]')) do |io|
|
||||
IO.popen({"FOO" => "bar"}, "echo #{@var}") do |io|
|
||||
io.read.should == "bar\n"
|
||||
end
|
||||
end
|
||||
|
||||
it "accepts a single String command, and an IO mode" do
|
||||
IO.popen({"FOO" => "bar"}, ruby_cmd('puts ENV["FOO"]'), "r") do |io|
|
||||
IO.popen({"FOO" => "bar"}, "echo #{@var}", "r") do |io|
|
||||
io.read.should == "bar\n"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -138,6 +138,16 @@ describe "Kernel.rand" do
|
|||
rand(KernelSpecs::CustomRangeFloat.new(1.0)..KernelSpecs::CustomRangeFloat.new(42.0)).should be_an_instance_of(KernelSpecs::CustomRangeFloat)
|
||||
rand(Time.now..Time.now).should be_an_instance_of(Time)
|
||||
end
|
||||
|
||||
it "is random on boot" do
|
||||
results = 2.times.map {
|
||||
out = ruby_exe('p rand', options: '--disable-gems')
|
||||
Float(out)
|
||||
}
|
||||
results.size.should == 2
|
||||
# this is technically flaky, but very unlikely in a good distribution
|
||||
results[0].should_not == results[1]
|
||||
end
|
||||
end
|
||||
|
||||
describe "Kernel#rand" do
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
main = self
|
||||
|
||||
describe :kernel_load, shared: true do
|
||||
before :each do
|
||||
CodeLoadingSpecs.spec_setup
|
||||
|
@ -95,13 +97,45 @@ describe :kernel_load, shared: true do
|
|||
@object.load(path, true)
|
||||
|
||||
Object.const_defined?(:LoadSpecWrap).should be_false
|
||||
|
||||
wrap_module = ScratchPad.recorded[1]
|
||||
wrap_module.should be_an_instance_of(Module)
|
||||
end
|
||||
|
||||
it "allows referencing outside namespaces" do
|
||||
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
|
||||
@object.load(path, true)
|
||||
|
||||
ScratchPad.recorded.first.should be_an_instance_of(Class)
|
||||
ScratchPad.recorded[0].should equal(String)
|
||||
end
|
||||
|
||||
it "sets self as a copy of the top-level main" do
|
||||
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
|
||||
@object.load(path, true)
|
||||
|
||||
top_level = ScratchPad.recorded[2]
|
||||
top_level.to_s.should == "main"
|
||||
top_level.method(:to_s).owner.should == top_level.singleton_class
|
||||
top_level.should_not equal(main)
|
||||
top_level.should be_an_instance_of(Object)
|
||||
end
|
||||
|
||||
it "includes modules included in main's singleton class in self's class" do
|
||||
mod = Module.new
|
||||
main.extend(mod)
|
||||
|
||||
main_ancestors = main.singleton_class.ancestors[1..-1]
|
||||
main_ancestors.first.should == mod
|
||||
|
||||
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
|
||||
@object.load(path, true)
|
||||
|
||||
top_level = ScratchPad.recorded[2]
|
||||
top_level_ancestors = top_level.singleton_class.ancestors[-main_ancestors.size..-1]
|
||||
top_level_ancestors.should == main_ancestors
|
||||
|
||||
wrap_module = ScratchPad.recorded[1]
|
||||
top_level.singleton_class.ancestors.should == [top_level.singleton_class, wrap_module, *main_ancestors]
|
||||
end
|
||||
|
||||
describe "with top-level methods" do
|
||||
|
|
|
@ -473,6 +473,12 @@ describe "Marshal.dump" do
|
|||
Marshal.dump(obj).should == "\x04\bo:\x0EException\a:\tmesg\"\bfoo:\abt[\x06\"\x12foo/bar.rb:10"
|
||||
end
|
||||
|
||||
it "dumps instance variables if they exist" do
|
||||
obj = Exception.new("foo")
|
||||
obj.instance_variable_set(:@ivar, 1)
|
||||
Marshal.dump(obj).should == "\x04\bo:\x0EException\b:\tmesg\"\bfoo:\abt0:\n@ivari\x06"
|
||||
end
|
||||
|
||||
it "dumps the cause for the exception" do
|
||||
exc = nil
|
||||
begin
|
||||
|
|
|
@ -531,6 +531,19 @@ describe :marshal_load, shared: true do
|
|||
loaded.message.should == obj.message
|
||||
loaded.backtrace.should == obj.backtrace
|
||||
end
|
||||
|
||||
it "loads an marshalled exception with ivars" do
|
||||
s = 'hi'
|
||||
arr = [:so, :so, s, s]
|
||||
obj = Exception.new("foo")
|
||||
obj.instance_variable_set :@arr, arr
|
||||
|
||||
loaded = Marshal.send(@method, "\x04\bo:\x0EException\b:\tmesg\"\bfoo:\abt0:\t@arr[\t:\aso;\t\"\ahi@\b")
|
||||
new_arr = loaded.instance_variable_get :@arr
|
||||
|
||||
loaded.message.should == obj.message
|
||||
new_arr.should == arr
|
||||
end
|
||||
end
|
||||
|
||||
describe "for an Object" do
|
||||
|
|
10
spec/ruby/core/matchdata/allocate_spec.rb
Normal file
10
spec/ruby/core/matchdata/allocate_spec.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "MatchData.allocate" do
|
||||
ruby_version_is "2.7" do
|
||||
it "is undefined" do
|
||||
# https://bugs.ruby-lang.org/issues/16294
|
||||
-> { MatchData.allocate }.should raise_error(NoMethodError)
|
||||
end
|
||||
end
|
||||
end
|
14
spec/ruby/core/matchdata/dup_spec.rb
Normal file
14
spec/ruby/core/matchdata/dup_spec.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe "MatchData#dup" do
|
||||
it "duplicates the match data" do
|
||||
original = /ll/.match("hello")
|
||||
original.instance_variable_set(:@custom_ivar, 42)
|
||||
duplicate = original.dup
|
||||
|
||||
duplicate.instance_variable_get(:@custom_ivar).should == 42
|
||||
original.regexp.should == duplicate.regexp
|
||||
original.string.should == duplicate.string
|
||||
original.offset(0).should == duplicate.offset(0)
|
||||
end
|
||||
end
|
|
@ -11,6 +11,12 @@ describe "MatchData#regexp" do
|
|||
m.regexp.should == /hay/
|
||||
end
|
||||
|
||||
it "returns the same Regexp used to match" do
|
||||
r = /hay/
|
||||
m = 'haystack'.match(r)
|
||||
m.regexp.object_id.should == r.object_id
|
||||
end
|
||||
|
||||
it "returns a Regexp for the result of gsub(String)" do
|
||||
'he[[o'.gsub('[', ']')
|
||||
$~.regexp.should == /\[/
|
||||
|
|
|
@ -652,6 +652,27 @@ describe "Module#autoload" do
|
|||
ModuleSpecs::Autoload::AutoloadDuringRequire.should be_kind_of(Class)
|
||||
end
|
||||
|
||||
it "does not call #require a second time and does not warn if feature sets and trigger autoload on itself" do
|
||||
main = TOPLEVEL_BINDING.eval("self")
|
||||
main.should_not_receive(:require)
|
||||
|
||||
-> {
|
||||
Kernel.require fixture(__FILE__, "autoload_self_during_require.rb")
|
||||
}.should_not complain(verbose: true)
|
||||
ModuleSpecs::Autoload::AutoloadSelfDuringRequire.should be_kind_of(Class)
|
||||
end
|
||||
|
||||
it "handles multiple autoloads in the same file" do
|
||||
$LOAD_PATH.unshift(File.expand_path('../fixtures/multi', __FILE__))
|
||||
begin
|
||||
require 'foo/bar_baz'
|
||||
ModuleSpecs::Autoload::Foo::Bar.should be_kind_of(Class)
|
||||
ModuleSpecs::Autoload::Foo::Baz.should be_kind_of(Class)
|
||||
ensure
|
||||
$LOAD_PATH.shift
|
||||
end
|
||||
end
|
||||
|
||||
it "calls #to_path on non-string filenames" do
|
||||
p = mock('path')
|
||||
p.should_receive(:to_path).and_return @non_existent
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module ModuleSpecs::Autoload
|
||||
autoload :AutoloadSelfDuringRequire, __FILE__
|
||||
class AutoloadSelfDuringRequire
|
||||
end
|
||||
end
|
|
@ -6,6 +6,9 @@ module ModuleSpecs
|
|||
|
||||
CONST = :plain_constant
|
||||
|
||||
class NamedClass
|
||||
end
|
||||
|
||||
module PrivConstModule
|
||||
PRIVATE_CONSTANT = 1
|
||||
private_constant :PRIVATE_CONSTANT
|
||||
|
|
6
spec/ruby/core/module/fixtures/multi/foo.rb
Normal file
6
spec/ruby/core/module/fixtures/multi/foo.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
module ModuleSpecs::Autoload
|
||||
module Foo
|
||||
autoload :Bar, 'foo/bar_baz'
|
||||
autoload :Baz, 'foo/bar_baz'
|
||||
end
|
||||
end
|
11
spec/ruby/core/module/fixtures/multi/foo/bar_baz.rb
Normal file
11
spec/ruby/core/module/fixtures/multi/foo/bar_baz.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
require 'foo'
|
||||
|
||||
module ModuleSpecs::Autoload
|
||||
module Foo
|
||||
class Bar
|
||||
end
|
||||
|
||||
class Baz
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,6 +5,23 @@ describe :set_visibility, shared: true do
|
|||
Module.should have_private_instance_method(@method, false)
|
||||
end
|
||||
|
||||
describe "with argument" do
|
||||
it "does not clone method from the ancestor when setting to the same visibility in a child" do
|
||||
visibility = @method
|
||||
parent = Module.new {
|
||||
def test_method; end
|
||||
send(visibility, :test_method)
|
||||
}
|
||||
|
||||
child = Module.new {
|
||||
include parent
|
||||
send(visibility, :test_method)
|
||||
}
|
||||
|
||||
child.should_not send(:"have_#{visibility}_instance_method", :test_method, false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "without arguments" do
|
||||
it "sets visibility to following method definitions" do
|
||||
visibility = @method
|
||||
|
|
|
@ -2,17 +2,44 @@ require_relative '../../spec_helper'
|
|||
require_relative 'fixtures/classes'
|
||||
|
||||
describe "Module#to_s" do
|
||||
it 'returns the name of the module if it has a name' do
|
||||
Enumerable.to_s.should == 'Enumerable'
|
||||
String.to_s.should == 'String'
|
||||
end
|
||||
|
||||
it "returns the full constant path leading to the module" do
|
||||
ModuleSpecs::LookupMod.to_s.should == "ModuleSpecs::LookupMod"
|
||||
end
|
||||
|
||||
it "works with an anonymous module" do
|
||||
m = Module.new
|
||||
m.to_s.should =~ /#<Module:0x[0-9a-f]+>/
|
||||
m.to_s.should =~ /\A#<Module:0x\h+>\z/
|
||||
end
|
||||
|
||||
it "works with an anonymous class" do
|
||||
c = Class.new
|
||||
c.to_s.should =~ /#<Class:0x[0-9a-f]+>/
|
||||
c.to_s.should =~ /\A#<Class:0x\h+>\z/
|
||||
end
|
||||
|
||||
it 'for the singleton class of an object of an anonymous class' do
|
||||
klass = Class.new
|
||||
obj = klass.new
|
||||
sclass = obj.singleton_class
|
||||
sclass.to_s.should == "#<Class:#{obj}>"
|
||||
sclass.to_s.should =~ /\A#<Class:#<#{klass}:0x\h+>>\z/
|
||||
sclass.to_s.should =~ /\A#<Class:#<#<Class:0x\h+>:0x\h+>>\z/
|
||||
end
|
||||
|
||||
it 'for a singleton class of a module includes the module name' do
|
||||
ModuleSpecs.singleton_class.to_s.should == '#<Class:ModuleSpecs>'
|
||||
end
|
||||
|
||||
it 'for a metaclass includes the class name' do
|
||||
ModuleSpecs::NamedClass.singleton_class.to_s.should == '#<Class:ModuleSpecs::NamedClass>'
|
||||
end
|
||||
|
||||
it 'for objects includes class name and object ID' do
|
||||
obj = ModuleSpecs::NamedClass.new
|
||||
obj.singleton_class.to_s.should =~ /\A#<Class:#<ModuleSpecs::NamedClass:0x\h+>>\z/
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,8 +56,37 @@ describe "Module#undef_method" do
|
|||
@module.send(:undef_method, :method_to_undef).should equal(@module)
|
||||
end
|
||||
|
||||
it "raises a NameError when passed a missing name" do
|
||||
-> { @module.send :undef_method, :not_exist }.should raise_error(NameError) { |e|
|
||||
it "raises a NameError when passed a missing name for a module" do
|
||||
-> { @module.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for module `#{@module}'/) { |e|
|
||||
# a NameError and not a NoMethodError
|
||||
e.class.should == NameError
|
||||
}
|
||||
end
|
||||
|
||||
it "raises a NameError when passed a missing name for a class" do
|
||||
klass = Class.new
|
||||
-> { klass.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for class `#{klass}'/) { |e|
|
||||
# a NameError and not a NoMethodError
|
||||
e.class.should == NameError
|
||||
}
|
||||
end
|
||||
|
||||
it "raises a NameError when passed a missing name for a singleton class" do
|
||||
klass = Class.new
|
||||
obj = klass.new
|
||||
sclass = obj.singleton_class
|
||||
|
||||
-> { sclass.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for class `#{sclass}'/) { |e|
|
||||
e.message.should include('`#<Class:#<#<Class:')
|
||||
|
||||
# a NameError and not a NoMethodError
|
||||
e.class.should == NameError
|
||||
}
|
||||
end
|
||||
|
||||
it "raises a NameError when passed a missing name for a metaclass" do
|
||||
klass = String.singleton_class
|
||||
-> { klass.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for class `String'/) { |e|
|
||||
# a NameError and not a NoMethodError
|
||||
e.class.should == NameError
|
||||
}
|
||||
|
|
|
@ -8,10 +8,7 @@ describe "Process.clock_getres" do
|
|||
# NOTE: Look at fixtures/clocks.rb for clock and OS-specific exclusions
|
||||
ProcessSpecs.clock_constants_for_resolution_checks.each do |name, value|
|
||||
it "matches the clock in practice for Process::#{name}" do
|
||||
times = []
|
||||
10_000.times do
|
||||
times << Process.clock_gettime(value, :nanosecond)
|
||||
end
|
||||
times = 10_000.times.map { Process.clock_gettime(value, :nanosecond) }
|
||||
reported = Process.clock_getres(value, :nanosecond)
|
||||
|
||||
# The clock should not be more accurate than reported (times should be
|
||||
|
|
|
@ -41,4 +41,97 @@ describe "Process.clock_gettime" do
|
|||
t2.should be_close(t1, TIME_TOLERANCE)
|
||||
end
|
||||
end
|
||||
|
||||
describe "supports the platform clocks mentioned in the documentation" do
|
||||
it "CLOCK_REALTIME" do
|
||||
Process.clock_gettime(Process::CLOCK_REALTIME).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_MONOTONIC" do
|
||||
Process.clock_gettime(Process::CLOCK_MONOTONIC).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
# These specs need macOS 10.12+ / darwin 16+
|
||||
guard_not -> { platform_is_not(:darwin) or RUBY_PLATFORM[/darwin\d+/].to_i >= 16 } do
|
||||
platform_is :linux, :openbsd, :darwin do
|
||||
it "CLOCK_PROCESS_CPUTIME_ID" do
|
||||
Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID).should be_an_instance_of(Float)
|
||||
end
|
||||
end
|
||||
|
||||
platform_is :linux, :freebsd, :openbsd, :darwin do
|
||||
it "CLOCK_THREAD_CPUTIME_ID" do
|
||||
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID).should be_an_instance_of(Float)
|
||||
end
|
||||
end
|
||||
|
||||
platform_is :freebsd, :openbsd do
|
||||
it "CLOCK_VIRTUAL" do
|
||||
Process.clock_gettime(Process::CLOCK_VIRTUAL).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_PROF" do
|
||||
Process.clock_gettime(Process::CLOCK_PROF).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_UPTIME" do
|
||||
Process.clock_gettime(Process::CLOCK_UPTIME).should be_an_instance_of(Float)
|
||||
end
|
||||
end
|
||||
|
||||
platform_is :linux, :darwin do
|
||||
it "CLOCK_MONOTONIC_RAW" do
|
||||
Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW).should be_an_instance_of(Float)
|
||||
end
|
||||
end
|
||||
|
||||
platform_is :darwin do
|
||||
it "CLOCK_MONOTONIC_RAW_APPROX" do
|
||||
Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW_APPROX).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_UPTIME_RAW and CLOCK_UPTIME_RAW_APPROX" do
|
||||
Process.clock_gettime(Process::CLOCK_UPTIME_RAW).should be_an_instance_of(Float)
|
||||
Process.clock_gettime(Process::CLOCK_UPTIME_RAW_APPROX).should be_an_instance_of(Float)
|
||||
end
|
||||
end
|
||||
|
||||
platform_is :freebsd do
|
||||
it "CLOCK_REALTIME_FAST and CLOCK_REALTIME_PRECISE" do
|
||||
Process.clock_gettime(Process::CLOCK_REALTIME_FAST).should be_an_instance_of(Float)
|
||||
Process.clock_gettime(Process::CLOCK_REALTIME_PRECISE).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_MONOTONIC_FAST and CLOCK_MONOTONIC_PRECISE" do
|
||||
Process.clock_gettime(Process::CLOCK_MONOTONIC_FAST).should be_an_instance_of(Float)
|
||||
Process.clock_gettime(Process::CLOCK_MONOTONIC_PRECISE).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_UPTIME_FAST and CLOCK_UPTIME_PRECISE" do
|
||||
Process.clock_gettime(Process::CLOCK_UPTIME_FAST).should be_an_instance_of(Float)
|
||||
Process.clock_gettime(Process::CLOCK_UPTIME_PRECISE).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_SECOND" do
|
||||
Process.clock_gettime(Process::CLOCK_SECOND).should be_an_instance_of(Float)
|
||||
end
|
||||
end
|
||||
|
||||
platform_is :linux do
|
||||
it "CLOCK_REALTIME_COARSE and CLOCK_REALTIME_ALARM" do
|
||||
Process.clock_gettime(Process::CLOCK_REALTIME_COARSE).should be_an_instance_of(Float)
|
||||
Process.clock_gettime(Process::CLOCK_REALTIME_ALARM).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_MONOTONIC_COARSE" do
|
||||
Process.clock_gettime(Process::CLOCK_MONOTONIC_COARSE).should be_an_instance_of(Float)
|
||||
end
|
||||
|
||||
it "CLOCK_BOOTTIME and CLOCK_BOOTTIME_ALARM" do
|
||||
Process.clock_gettime(Process::CLOCK_BOOTTIME).should be_an_instance_of(Float)
|
||||
Process.clock_gettime(Process::CLOCK_BOOTTIME_ALARM).should be_an_instance_of(Float)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -200,9 +200,9 @@ describe "Process.exec" do
|
|||
it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do
|
||||
map_fd_fixture = fixture __FILE__, "map_fd.rb"
|
||||
cmd = <<-EOC
|
||||
f = File.open("#{@name}", "w+")
|
||||
f = File.open(#{@name.inspect}, "w+")
|
||||
child_fd = f.fileno + 1
|
||||
File.open("#{@child_fd_file}", "w") { |io| io.print child_fd }
|
||||
File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd }
|
||||
Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f }
|
||||
EOC
|
||||
|
||||
|
@ -212,6 +212,35 @@ describe "Process.exec" do
|
|||
|
||||
File.read(@name).should == "writing to fd: #{child_fd}"
|
||||
end
|
||||
|
||||
it "lets the process after exec have specified file descriptor despite close_on_exec" do
|
||||
map_fd_fixture = fixture __FILE__, "map_fd.rb"
|
||||
cmd = <<-EOC
|
||||
f = File.open(#{@name.inspect}, 'w+')
|
||||
puts(f.fileno, f.close_on_exec?)
|
||||
STDOUT.flush
|
||||
Process.exec("#{ruby_cmd(map_fd_fixture)} \#{f.fileno}", f.fileno => f.fileno)
|
||||
EOC
|
||||
|
||||
output = ruby_exe(cmd, escape: true)
|
||||
child_fd, close_on_exec = output.split
|
||||
|
||||
child_fd.to_i.should > STDERR.fileno
|
||||
close_on_exec.should == 'true'
|
||||
File.read(@name).should == "writing to fd: #{child_fd}"
|
||||
end
|
||||
|
||||
it "sets close_on_exec to false on specified fd even when it fails" do
|
||||
cmd = <<-EOC
|
||||
f = File.open(#{__FILE__.inspect}, 'r')
|
||||
puts(f.close_on_exec?)
|
||||
Process.exec('/', f.fileno => f.fileno) rescue nil
|
||||
puts(f.close_on_exec?)
|
||||
EOC
|
||||
|
||||
output = ruby_exe(cmd, escape: true)
|
||||
output.split.should == ['true', 'false']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,11 +3,15 @@ module ProcessSpecs
|
|||
if defined?(MSpecScript::SYSTEM_RUBY)
|
||||
context.send(:before, :all) do
|
||||
@ruby = ::RUBY_EXE
|
||||
Object.const_set(:RUBY_EXE, MSpecScript::SYSTEM_RUBY)
|
||||
suppress_warning {
|
||||
Object.const_set(:RUBY_EXE, MSpecScript::SYSTEM_RUBY)
|
||||
}
|
||||
end
|
||||
|
||||
context.send(:after, :all) do
|
||||
Object.const_set(:RUBY_EXE, @ruby)
|
||||
suppress_warning {
|
||||
Object.const_set(:RUBY_EXE, @ruby)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Status#==" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns true when compared to the integer status of an exited child" do
|
||||
ruby_exe("exit(29)")
|
||||
$?.to_i.should == $?
|
||||
$?.should == $?.to_i
|
||||
end
|
||||
|
||||
it "returns true when compared to the integer status of a terminated child" do
|
||||
ruby_exe("Process.kill(:KILL, $$); exit(29)")
|
||||
$?.to_i.should == $?
|
||||
$?.should == $?.to_i
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ describe "Process::Status#exitstatus" do
|
|||
|
||||
describe "for a child that raised SignalException" do
|
||||
before :each do
|
||||
ruby_exe("raise SignalException, 'SIGTERM'")
|
||||
ruby_exe("Process.kill(:KILL, $$); exit(42)")
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Status#termsig" do
|
||||
|
||||
describe "for a child that exited normally" do
|
||||
|
||||
before :each do
|
||||
ruby_exe("exit(0)")
|
||||
end
|
||||
|
@ -26,26 +24,20 @@ describe "Process::Status#termsig" do
|
|||
end
|
||||
|
||||
describe "for a child that was sent a signal" do
|
||||
|
||||
before :each do
|
||||
ruby_exe("Process.kill(:KILL, $$); exit(42)")
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
|
||||
it "returns the signal" do
|
||||
$?.termsig.should == Signal.list["KILL"]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
platform_is :windows do
|
||||
|
||||
it "always returns nil" do
|
||||
$?.termsig.should be_nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Status#to_i" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it "returns an integer when the child exits" do
|
||||
ruby_exe('exit 48')
|
||||
$?.to_i.should be_an_instance_of(Integer)
|
||||
end
|
||||
|
||||
it "returns an integer when the child is signaled" do
|
||||
ruby_exe('raise SignalException, "TERM"')
|
||||
$?.to_i.should be_an_instance_of(Integer)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,21 +7,19 @@ describe "Process.times" do
|
|||
|
||||
it "returns current cpu times" do
|
||||
t = Process.times
|
||||
user = t.utime
|
||||
|
||||
# Do busy work for a wall-clock interval.
|
||||
start = Time.now
|
||||
1 until (Time.now - start) > 0.5
|
||||
1 until Process.times.utime > user
|
||||
Process.times.utime.should > user
|
||||
end
|
||||
|
||||
# Ensure times is larger. NOTE that there is no
|
||||
# guarantee of an upper bound since anything may be
|
||||
# happening at the OS level, so we ONLY check that at
|
||||
# least an interval has elapsed. Also, we are assuming
|
||||
# there is a correlation between wall clock time and
|
||||
# process time. In practice, there is an observed
|
||||
# discrepancy often 10% or greater. In other words,
|
||||
# this is a very fuzzy test.
|
||||
t2 = Process.times
|
||||
diff = (t2.utime + t2.stime) - (t.utime + t.stime)
|
||||
diff.should > 0
|
||||
ruby_version_is "2.5" do
|
||||
platform_is_not :windows do
|
||||
it "uses getrusage when available to improve precision beyond milliseconds" do
|
||||
times = 100.times.map { Process.times }
|
||||
times.count { |t| ((t.utime * 1e6).to_i % 1000) > 0 }.should > 0
|
||||
times.count { |t| ((t.stime * 1e6).to_i % 1000) > 0 }.should > 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Tms#cstime" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
||||
|
||||
describe "Process::Tms#cstime=" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Tms#cutime" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
||||
|
||||
describe "Process::Tms#cutime=" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Tms.[]" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Tms.members" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Tms.new" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Tms#stime" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
||||
|
||||
describe "Process::Tms#stime=" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
require_relative '../../../spec_helper'
|
||||
|
||||
describe "Process::Tms#utime" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
||||
|
||||
describe "Process::Tms#utime=" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
|
@ -38,6 +38,10 @@ describe "Regexp#match" do
|
|||
-> { Regexp.allocate.match('foo') }.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it "raises TypeError on an uninitialized Regexp" do
|
||||
-> { Regexp.allocate.match('foo'.encode("UTF-16LE")) }.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
describe "with [string, position]" do
|
||||
describe "when given a positive position" do
|
||||
it "matches the input at a given position" do
|
||||
|
|
7
spec/ruby/core/struct/clone_spec.rb
Normal file
7
spec/ruby/core/struct/clone_spec.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
require_relative 'shared/dup'
|
||||
|
||||
describe "Struct-based class#clone" do
|
||||
it_behaves_like :struct_dup, :clone
|
||||
end
|
|
@ -1,8 +1,11 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
require_relative 'shared/dup'
|
||||
|
||||
describe "Struct-based class#dup" do
|
||||
|
||||
it_behaves_like :struct_dup, :dup
|
||||
|
||||
# From https://github.com/jruby/jruby/issues/3686
|
||||
it "retains an included module in the ancestor chain for the struct's singleton class" do
|
||||
klass = Struct.new(:foo)
|
||||
|
|
16
spec/ruby/core/struct/instance_variable_get_spec.rb
Normal file
16
spec/ruby/core/struct/instance_variable_get_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
|
||||
describe "Struct#instance_variable_get" do
|
||||
it "returns nil for attributes" do
|
||||
car = StructClasses::Car.new("Hugo", "Foo", "1972")
|
||||
car.instance_variable_get(:@make).should be_nil
|
||||
end
|
||||
|
||||
it "returns a user value for variables with the same name as attributes" do
|
||||
car = StructClasses::Car.new("Hugo", "Foo", "1972")
|
||||
car.instance_variable_set :@make, "explicit"
|
||||
car.instance_variable_get(:@make).should == "explicit"
|
||||
car.make.should == "Hugo"
|
||||
end
|
||||
end
|
|
@ -74,6 +74,10 @@ describe "Struct.new" do
|
|||
end
|
||||
end
|
||||
|
||||
it "raises ArgumentError when there is a duplicate member" do
|
||||
-> { Struct.new(:foo, :foo) }.should raise_error(ArgumentError, "duplicate member: foo")
|
||||
end
|
||||
|
||||
it "raises a TypeError if object is not a Symbol" do
|
||||
obj = mock(':ruby')
|
||||
def obj.to_sym() :ruby end
|
||||
|
@ -147,7 +151,6 @@ describe "Struct.new" do
|
|||
context "keyword_init: true option" do
|
||||
before :all do
|
||||
@struct_with_kwa = Struct.new(:name, :legs, keyword_init: true)
|
||||
@struct_without_kwa = Struct.new(:name, :legs, keyword_init: false)
|
||||
end
|
||||
|
||||
it "creates a class that accepts keyword arguments to initialize" do
|
||||
|
@ -156,6 +159,10 @@ describe "Struct.new" do
|
|||
obj.legs.should == 4
|
||||
end
|
||||
|
||||
it "raises when there is a duplicate member" do
|
||||
-> { Struct.new(:foo, :foo, keyword_init: true) }.should raise_error(ArgumentError, "duplicate member: foo")
|
||||
end
|
||||
|
||||
describe "new class instantiation" do
|
||||
it "accepts arguments as hash as well" do
|
||||
obj = @struct_with_kwa.new({name: "elefant", legs: 4})
|
||||
|
@ -163,6 +170,18 @@ describe "Struct.new" do
|
|||
obj.legs.should == 4
|
||||
end
|
||||
|
||||
it "allows missing arguments" do
|
||||
obj = @struct_with_kwa.new(name: "elefant")
|
||||
obj.name.should == "elefant"
|
||||
obj.legs.should be_nil
|
||||
end
|
||||
|
||||
it "allows no arguments" do
|
||||
obj = @struct_with_kwa.new
|
||||
obj.name.should be_nil
|
||||
obj.legs.should be_nil
|
||||
end
|
||||
|
||||
it "raises ArgumentError when passed not declared keyword argument" do
|
||||
-> {
|
||||
@struct_with_kwa.new(name: "elefant", legs: 4, foo: "bar")
|
||||
|
@ -184,6 +203,10 @@ describe "Struct.new" do
|
|||
end
|
||||
|
||||
context "keyword_init: false option" do
|
||||
before :all do
|
||||
@struct_without_kwa = Struct.new(:name, :legs, keyword_init: false)
|
||||
end
|
||||
|
||||
it "behaves like it does without :keyword_init option" do
|
||||
obj = @struct_without_kwa.new("elefant", 4)
|
||||
obj.name.should == "elefant"
|
||||
|
|
9
spec/ruby/core/struct/shared/dup.rb
Normal file
9
spec/ruby/core/struct/shared/dup.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
describe :struct_dup, shared: true do
|
||||
it "duplicates members" do
|
||||
klass = Struct.new(:foo, :bar)
|
||||
instance = klass.new(14, 2)
|
||||
duped = instance.send(@method)
|
||||
duped.foo.should == 14
|
||||
duped.bar.should == 2
|
||||
end
|
||||
end
|
|
@ -113,6 +113,12 @@ describe "Time.new with a utc_offset argument" do
|
|||
it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do
|
||||
-> { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "raises ArgumentError if the month is greater than 12" do
|
||||
# For some reason MRI uses a different message for month in 13-15 and month>=16
|
||||
-> { Time.new(2000, 13, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, /(mon|argument) out of range/)
|
||||
-> { Time.new(2000, 16, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, "argument out of range")
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.6" do
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
class LoadSpecWrap
|
||||
ScratchPad << self
|
||||
ScratchPad << String
|
||||
end
|
||||
|
||||
def load_wrap_specs_top_level_method
|
||||
end
|
||||
ScratchPad << method(:load_wrap_specs_top_level_method).owner
|
||||
|
||||
ScratchPad << self
|
||||
|
|
|
@ -48,6 +48,13 @@ describe "The =~ operator with named captures" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "on syntax of 'string_literal' =~ /regexp/" do
|
||||
it "does not set local variables" do
|
||||
'string literal' =~ /(?<matched>str)(?<unmatched>lit)?/
|
||||
local_variables.should == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "on syntax of string_variable =~ /regexp/" do
|
||||
it "does not set local variables" do
|
||||
@string =~ /(?<matched>foo)(?<unmatched>bar)?/
|
||||
|
|
|
@ -42,6 +42,10 @@ describe "Regexps with encoding modifiers" do
|
|||
/./n.encoding.should == Encoding::US_ASCII
|
||||
end
|
||||
|
||||
it 'uses BINARY when is not initialized' do
|
||||
Regexp.allocate.encoding.should == Encoding::BINARY
|
||||
end
|
||||
|
||||
it 'uses BINARY as /n encoding if not all chars are 7-bit' do
|
||||
/\xFF/n.encoding.should == Encoding::BINARY
|
||||
end
|
||||
|
@ -100,4 +104,16 @@ describe "Regexps with encoding modifiers" do
|
|||
it "selects last of multiple encoding specifiers" do
|
||||
/foo/ensuensuens.should == /foo/s
|
||||
end
|
||||
|
||||
it "raises Encoding::CompatibilityError when trying match against different encodings" do
|
||||
-> { /\A[[:space:]]*\z/.match(" ".encode("UTF-16LE")) }.should raise_error(Encoding::CompatibilityError)
|
||||
end
|
||||
|
||||
it "raises Encoding::CompatibilityError when trying match? against different encodings" do
|
||||
-> { /\A[[:space:]]*\z/.match?(" ".encode("UTF-16LE")) }.should raise_error(Encoding::CompatibilityError)
|
||||
end
|
||||
|
||||
it "raises Encoding::CompatibilityError when trying =~ against different encodings" do
|
||||
-> { /\A[[:space:]]*\z/ =~ " ".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,4 +6,20 @@ describe "Base64#decode64" do
|
|||
it "returns the Base64-decoded version of the given string" do
|
||||
Base64.decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n").should == "Send reinforcements"
|
||||
end
|
||||
|
||||
it "returns the Base64-decoded version of the given shared string" do
|
||||
Base64.decode64("base64: U2VuZCByZWluZm9yY2VtZW50cw==\n".split(" ").last).should == "Send reinforcements"
|
||||
end
|
||||
|
||||
it "returns the Base64-decoded version of the given string with wrong padding" do
|
||||
Base64.decode64("XU2VuZCByZWluZm9yY2VtZW50cw===").should == "]M\x95\xB9\x90\x81\xC9\x95\xA5\xB9\x99\xBD\xC9\x8D\x95\xB5\x95\xB9\xD1\xCC".b
|
||||
end
|
||||
|
||||
it "returns the Base64-decoded version of the given string that contains an invalid character" do
|
||||
Base64.decode64("%3D").should == "\xDC".b
|
||||
end
|
||||
|
||||
it "returns a binary encoded string" do
|
||||
Base64.decode64("SEk=").encoding.should == Encoding::BINARY
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,4 +11,13 @@ describe "Base64#encode64" do
|
|||
it "returns the Base64-encoded version of the given string" do
|
||||
Base64.encode64('Send reinforcements').should == "U2VuZCByZWluZm9yY2VtZW50cw==\n"
|
||||
end
|
||||
|
||||
it "returns the Base64-encoded version of the given shared string" do
|
||||
Base64.encode64("Now is the time for all good coders\nto learn Ruby".split("\n").last).should ==
|
||||
"dG8gbGVhcm4gUnVieQ==\n"
|
||||
end
|
||||
|
||||
it "returns a US_ASCII encoded string" do
|
||||
Base64.encode64("HI").encoding.should == Encoding::US_ASCII
|
||||
end
|
||||
end
|
||||
|
|
41
spec/ruby/library/base64/strict_decode64_spec.rb
Normal file
41
spec/ruby/library/base64/strict_decode64_spec.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
require 'base64'
|
||||
|
||||
describe "Base64#strict_decode64" do
|
||||
it "returns the Base64-decoded version of the given string" do
|
||||
Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==").should == "Send reinforcements"
|
||||
end
|
||||
|
||||
it "returns the Base64-decoded version of the given shared string" do
|
||||
Base64.strict_decode64("base64: U2VuZCByZWluZm9yY2VtZW50cw==".split(" ").last).should == "Send reinforcements"
|
||||
end
|
||||
|
||||
it "raises ArgumentError when the given string contains CR" do
|
||||
-> do
|
||||
Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==\r")
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "raises ArgumentError when the given string contains LF" do
|
||||
-> do
|
||||
Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n")
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "raises ArgumentError when the given string has wrong padding" do
|
||||
-> do
|
||||
Base64.strict_decode64("=U2VuZCByZWluZm9yY2VtZW50cw==")
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "raises ArgumentError when the given string contains an invalid character" do
|
||||
-> do
|
||||
Base64.strict_decode64("%3D")
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "returns a binary encoded string" do
|
||||
Base64.strict_decode64("SEk=").encoding.should == Encoding::BINARY
|
||||
end
|
||||
end
|
19
spec/ruby/library/base64/strict_encode64_spec.rb
Normal file
19
spec/ruby/library/base64/strict_encode64_spec.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
require 'base64'
|
||||
|
||||
describe "Base64#strict_encode64" do
|
||||
it "returns the Base64-encoded version of the given string" do
|
||||
Base64.strict_encode64("Now is the time for all good coders\nto learn Ruby").should ==
|
||||
"Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4gUnVieQ=="
|
||||
end
|
||||
|
||||
it "returns the Base64-encoded version of the given shared string" do
|
||||
Base64.strict_encode64("Now is the time for all good coders\nto learn Ruby".split("\n").last).should ==
|
||||
"dG8gbGVhcm4gUnVieQ=="
|
||||
end
|
||||
|
||||
it "returns a US_ASCII encoded string" do
|
||||
Base64.strict_encode64("HI").encoding.should == Encoding::US_ASCII
|
||||
end
|
||||
end
|
|
@ -24,6 +24,12 @@ describe "Kernel#BigDecimal" do
|
|||
}
|
||||
end
|
||||
|
||||
it "BigDecimal(Rational) with bigger-than-double numerator" do
|
||||
rational = 99999999999999999999/100r
|
||||
rational.numerator.should > 2**64
|
||||
BigDecimal(rational, 100).to_s.should == "0.99999999999999999999e18"
|
||||
end
|
||||
|
||||
it "accepts significant digits >= given precision" do
|
||||
BigDecimal("3.1415923", 10).precs[1].should >= 10
|
||||
end
|
||||
|
@ -33,8 +39,8 @@ describe "Kernel#BigDecimal" do
|
|||
BigDecimal(pi_string).precs[1].should >= pi_string.size-1
|
||||
end
|
||||
|
||||
it "ignores leading whitespace" do
|
||||
BigDecimal(" \t\n \r1234").should == BigDecimal("1234")
|
||||
it "ignores leading and trailing whitespace" do
|
||||
BigDecimal(" \t\n \r1234\t\r\n ").should == BigDecimal("1234")
|
||||
BigDecimal(" \t\n \rNaN \n").nan?.should == true
|
||||
BigDecimal(" \t\n \rInfinity \n").infinite?.should == 1
|
||||
BigDecimal(" \t\n \r-Infinity \n").infinite?.should == -1
|
||||
|
@ -159,4 +165,93 @@ describe "Kernel#BigDecimal" do
|
|||
BigDecimal(0.0, Float::DIG).sign.should == 1
|
||||
end
|
||||
|
||||
it "pre-coerces long integers" do
|
||||
BigDecimal(3).add(1 << 50, 3).should == BigDecimal('0.113e16')
|
||||
end
|
||||
|
||||
describe "when interacting with Rational" do
|
||||
before :each do
|
||||
@a = BigDecimal('166.666666666')
|
||||
@b = Rational(500, 3)
|
||||
@c = @a - @b
|
||||
end
|
||||
|
||||
# Check the input is as we understand it
|
||||
|
||||
it "has the LHS print as expected" do
|
||||
@a.to_s.should == "0.166666666666e3"
|
||||
@a.to_f.to_s.should == "166.666666666"
|
||||
Float(@a).to_s.should == "166.666666666"
|
||||
end
|
||||
|
||||
it "has the RHS print as expected" do
|
||||
@b.to_s.should == "500/3"
|
||||
@b.to_f.to_s.should == "166.66666666666666"
|
||||
Float(@b).to_s.should == "166.66666666666666"
|
||||
end
|
||||
|
||||
it "has the expected precision on the LHS" do
|
||||
@a.precs[0].should == 18
|
||||
end
|
||||
|
||||
it "has the expected maximum precision on the LHS" do
|
||||
@a.precs[1].should == 27
|
||||
end
|
||||
|
||||
it "produces the expected result when done via Float" do
|
||||
(Float(@a) - Float(@b)).to_s.should == "-6.666596163995564e-10"
|
||||
end
|
||||
|
||||
it "produces the expected result when done via to_f" do
|
||||
(@a.to_f - @b.to_f).to_s.should == "-6.666596163995564e-10"
|
||||
end
|
||||
|
||||
# Check underlying methods work as we understand
|
||||
|
||||
it "BigDecimal precision is the number of digits rounded up to a multiple of nine" do
|
||||
1.upto(100) do |n|
|
||||
b = BigDecimal('4' * n)
|
||||
precs, _ = b.precs
|
||||
(precs >= 9).should be_true
|
||||
(precs >= n).should be_true
|
||||
(precs % 9).should == 0
|
||||
end
|
||||
BigDecimal('NaN').precs[0].should == 9
|
||||
end
|
||||
|
||||
it "BigDecimal maximum precision is nine more than precision except for abnormals" do
|
||||
1.upto(100) do |n|
|
||||
b = BigDecimal('4' * n)
|
||||
precs, max = b.precs
|
||||
max.should == precs + 9
|
||||
end
|
||||
BigDecimal('NaN').precs[1].should == 9
|
||||
end
|
||||
|
||||
it "BigDecimal(Rational, 18) produces the result we expect" do
|
||||
BigDecimal(@b, 18).to_s.should == "0.166666666666666667e3"
|
||||
end
|
||||
|
||||
it "BigDecimal(Rational, BigDecimal.precs[0]) produces the result we expect" do
|
||||
BigDecimal(@b, @a.precs[0]).to_s.should == "0.166666666666666667e3"
|
||||
end
|
||||
|
||||
# Check the top-level expression works as we expect
|
||||
|
||||
it "produces a BigDecimal" do
|
||||
@c.class.should == BigDecimal
|
||||
end
|
||||
|
||||
it "produces the expected result" do
|
||||
@c.should == BigDecimal("-0.666667e-9")
|
||||
@c.to_s.should == "-0.666667e-9"
|
||||
end
|
||||
|
||||
it "produces the correct class for other arithmetic operators" do
|
||||
(@a + @b).class.should == BigDecimal
|
||||
(@a * @b).class.should == BigDecimal
|
||||
(@a / @b).class.should == BigDecimal
|
||||
(@a % @b).class.should == BigDecimal
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -66,4 +66,39 @@ describe "ConditionVariable#signal" do
|
|||
# released in the same order
|
||||
r2.should == r1
|
||||
end
|
||||
|
||||
it "allows control to be passed between a pair of threads" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
repeats = 100
|
||||
in_synchronize = false
|
||||
|
||||
t1 = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
repeats.times do
|
||||
cv.wait(m)
|
||||
cv.signal
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Make sure t1 is waiting for a signal before launching t2.
|
||||
Thread.pass until in_synchronize
|
||||
Thread.pass until t1.status == 'sleep'
|
||||
|
||||
t2 = Thread.new do
|
||||
m.synchronize do
|
||||
repeats.times do
|
||||
cv.signal
|
||||
cv.wait(m)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Check that both threads terminated without exception
|
||||
t1.join
|
||||
t2.join
|
||||
m.locked?.should == false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,8 +35,9 @@ describe 'Coverage.result' do
|
|||
Coverage.start
|
||||
require @class_file.chomp('.rb')
|
||||
Coverage.result
|
||||
-> { Coverage.result }
|
||||
.should raise_error(RuntimeError, 'coverage measurement is not enabled')
|
||||
-> {
|
||||
Coverage.result
|
||||
}.should raise_error(RuntimeError, 'coverage measurement is not enabled')
|
||||
end
|
||||
|
||||
it 'second run should give same result' do
|
||||
|
|
|
@ -35,3 +35,10 @@ describe "Date.iso8601" do
|
|||
-> { Date.iso8601(Object.new) }.should raise_error(TypeError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Date._iso8601" do
|
||||
it "returns an empty hash if the argument is a invalid Date" do
|
||||
h = Date._iso8601('invalid')
|
||||
h.should == {}
|
||||
end
|
||||
end
|
||||
|
|
13
spec/ruby/library/date/rfc3339_spec.rb
Normal file
13
spec/ruby/library/date/rfc3339_spec.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
require_relative '../../spec_helper'
|
||||
require 'date'
|
||||
|
||||
describe "Date.rfc3339" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
end
|
||||
|
||||
describe "Date._rfc3339" do
|
||||
it "returns an empty hash if the argument is a invalid Date" do
|
||||
h = Date._rfc3339('invalid')
|
||||
h.should == {}
|
||||
end
|
||||
end
|
7
spec/ruby/library/mkmf/mkmf_spec.rb
Normal file
7
spec/ruby/library/mkmf/mkmf_spec.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
describe 'mkmf' do
|
||||
it 'can be required with --enable-frozen-string-literal' do
|
||||
ruby_exe('p MakeMakefile', options: '-rmkmf --enable-frozen-string-literal').should == "MakeMakefile\n"
|
||||
end
|
||||
end
|
|
@ -23,6 +23,18 @@ describe 'RbConfig::CONFIG' do
|
|||
File.should.exist?("#{archdir}/etc.#{RbConfig::CONFIG['DLEXT']}")
|
||||
end
|
||||
end
|
||||
|
||||
it "contains no frozen strings even with --enable-frozen-string-literal" do
|
||||
ruby_exe(<<-RUBY, options: '--enable-frozen-string-literal').should == "Done\n"
|
||||
require 'rbconfig'
|
||||
RbConfig::CONFIG.each do |k, v|
|
||||
if v.frozen?
|
||||
puts "\#{k} Failure"
|
||||
end
|
||||
end
|
||||
puts 'Done'
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
describe "RbConfig::TOPDIR" do
|
||||
|
|
42
spec/ruby/library/rbconfig/sizeof/limits_spec.rb
Normal file
42
spec/ruby/library/rbconfig/sizeof/limits_spec.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require 'rbconfig/sizeof'
|
||||
|
||||
ruby_version_is "2.5" do
|
||||
describe "RbConfig::LIMITS" do
|
||||
it "is a Hash" do
|
||||
RbConfig::LIMITS.should be_kind_of(Hash)
|
||||
end
|
||||
|
||||
it "has string keys and numeric values" do
|
||||
RbConfig::LIMITS.each do |key, value|
|
||||
key.should be_kind_of String
|
||||
value.should be_kind_of Numeric
|
||||
end
|
||||
end
|
||||
|
||||
it "contains FIXNUM_MIN and FIXNUM_MAX" do
|
||||
RbConfig::LIMITS["FIXNUM_MIN"].should < 0
|
||||
RbConfig::LIMITS["FIXNUM_MAX"].should > 0
|
||||
end
|
||||
|
||||
it "contains CHAR_MIN and CHAR_MAX" do
|
||||
RbConfig::LIMITS["CHAR_MIN"].should <= 0
|
||||
RbConfig::LIMITS["CHAR_MAX"].should > 0
|
||||
end
|
||||
|
||||
it "contains SHRT_MIN and SHRT_MAX" do
|
||||
RbConfig::LIMITS["SHRT_MIN"].should == -32768
|
||||
RbConfig::LIMITS["SHRT_MAX"].should == 32767
|
||||
end
|
||||
|
||||
it "contains INT_MIN and INT_MAX" do
|
||||
RbConfig::LIMITS["INT_MIN"].should < 0
|
||||
RbConfig::LIMITS["INT_MAX"].should > 0
|
||||
end
|
||||
|
||||
it "contains LONG_MIN and LONG_MAX" do
|
||||
RbConfig::LIMITS["LONG_MIN"].should < 0
|
||||
RbConfig::LIMITS["LONG_MAX"].should > 0
|
||||
end
|
||||
end
|
||||
end
|
22
spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
Normal file
22
spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require_relative '../../spec_helper'
|
||||
require 'rbconfig'
|
||||
|
||||
describe "RbConfig::CONFIG['UNICODE_EMOJI_VERSION']" do
|
||||
ruby_version_is "2.6"..."2.6.2" do
|
||||
it "is 11.0 for Ruby 2.6.0 and 2.6.1" do
|
||||
RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "11.0"
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.6.2"..."2.7" do
|
||||
it "is 12.0 for Ruby 2.6.2+" do
|
||||
RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "12.0"
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
it "is 12.1 for Ruby 2.7" do
|
||||
RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "12.1"
|
||||
end
|
||||
end
|
||||
end
|
34
spec/ruby/library/rbconfig/unicode_version_spec.rb
Normal file
34
spec/ruby/library/rbconfig/unicode_version_spec.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
require_relative '../../spec_helper'
|
||||
require 'rbconfig'
|
||||
|
||||
describe "RbConfig::CONFIG['UNICODE_VERSION']" do
|
||||
ruby_version_is ""..."2.5" do
|
||||
it "is 9.0.0 for Ruby 2.4" do
|
||||
RbConfig::CONFIG['UNICODE_VERSION'].should == "9.0.0"
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.5"..."2.6" do
|
||||
it "is 10.0.0 for Ruby 2.5" do
|
||||
RbConfig::CONFIG['UNICODE_VERSION'].should == "10.0.0"
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.6"..."2.6.2" do
|
||||
it "is 11.0.0 for Ruby 2.6.0 and 2.6.1" do
|
||||
RbConfig::CONFIG['UNICODE_VERSION'].should == "11.0.0"
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.6.2"..."2.6.3" do
|
||||
it "is 12.0.0 for Ruby 2.6.2" do
|
||||
RbConfig::CONFIG['UNICODE_VERSION'].should == "12.0.0"
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.6.3" do
|
||||
it "is 12.1.0 for Ruby 2.6.3+ and Ruby 2.7" do
|
||||
RbConfig::CONFIG['UNICODE_VERSION'].should == "12.1.0"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,8 +6,8 @@ ruby_version_is ''...'2.7' do
|
|||
|
||||
describe "IO#scanf" do
|
||||
before :each do
|
||||
@hw = File.open(fixture(__FILE__, 'helloworld.txt'), 'r')
|
||||
@data = File.open(fixture(__FILE__, 'date.txt'), 'r')
|
||||
@hw = File.open(fixture(__FILE__, 'helloworld.txt'), 'rb')
|
||||
@data = File.open(fixture(__FILE__, 'date.txt'), 'rb')
|
||||
end
|
||||
|
||||
after :each do
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue