1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
This commit is contained in:
Benoit Daloze 2019-11-30 21:26:52 +01:00
parent ab8345271e
commit 1243255c3a
174 changed files with 1780 additions and 426 deletions

View file

@ -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

View file

@ -1,7 +1,7 @@
# The Ruby Spec Suite
[![Build Status](https://travis-ci.org/ruby/spec.svg)](https://travis-ci.org/ruby/spec)
[![Build Status](https://ci.appveyor.com/api/projects/status/1gs6f399320o44b1?svg=true)](https://ci.appveyor.com/project/eregon/spec-x948i)
[![Actions Build Status](https://github.com/ruby/spec/workflows/CI/badge.svg?branch=master)](https://github.com/ruby/spec/actions)
[![Windows Actions Build Status](https://github.com/ruby/spec/workflows/Windows/badge.svg?branch=master)](https://github.com/ruby/spec/actions)
[![Gitter](https://badges.gitter.im/ruby/spec.svg)](https://gitter.im/ruby/spec)
The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language.

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1 +1,7 @@
require_relative '../../spec_helper'
describe "ENV.rehash" do
it "returns nil" do
ENV.rehash.should == nil
end
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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] }

View file

@ -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

View file

@ -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

View file

@ -1,5 +0,0 @@
require_relative '../../spec_helper'
describe "NoMethodError#args" do
it "needs to be reviewed for spec completeness"
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View 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

View file

@ -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 == /\[/

View file

@ -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

View file

@ -0,0 +1,5 @@
module ModuleSpecs::Autoload
autoload :AutoloadSelfDuringRequire, __FILE__
class AutoloadSelfDuringRequire
end
end

View file

@ -6,6 +6,9 @@ module ModuleSpecs
CONST = :plain_constant
class NamedClass
end
module PrivConstModule
PRIVATE_CONSTANT = 1
private_constant :PRIVATE_CONSTANT

View file

@ -0,0 +1,6 @@
module ModuleSpecs::Autoload
module Foo
autoload :Bar, 'foo/bar_baz'
autoload :Baz, 'foo/bar_baz'
end
end

View file

@ -0,0 +1,11 @@
require 'foo'
module ModuleSpecs::Autoload
module Foo
class Bar
end
class Baz
end
end
end

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,5 +0,0 @@
require_relative '../../../spec_helper'
describe "Process::Tms.[]" do
it "needs to be reviewed for spec completeness"
end

View file

@ -1,5 +0,0 @@
require_relative '../../../spec_helper'
describe "Process::Tms.members" do
it "needs to be reviewed for spec completeness"
end

View file

@ -1,5 +0,0 @@
require_relative '../../../spec_helper'
describe "Process::Tms.new" do
it "needs to be reviewed for spec completeness"
end

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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)

View 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

View file

@ -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"

View 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

View file

@ -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

View file

@ -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

View file

@ -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)?/

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View 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

View file

@ -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

View 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

View 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

View 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

View file

@ -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