This commit is contained in:
Benoit Daloze 2024-11-06 21:57:34 +01:00
parent 9bc63e7ba0
commit fdc82cca83
95 changed files with 1939 additions and 359 deletions

View File

@ -5,9 +5,13 @@ AllCops:
DisplayCopNames: true
Exclude:
- command_line/fixtures/bad_syntax.rb
- core/exception/fixtures/syntax_error.rb
DisabledByDefault: true
NewCops: disable
Layout/IndentationConsistency:
Enabled: true
Layout/TrailingWhitespace:
Enabled: true
@ -43,9 +47,23 @@ Lint/InterpolationCheck:
Lint/LiteralAsCondition:
Enabled: false
# Required to support Ruby 3.0
Lint/RedundantRequireStatement:
Exclude:
- core/fiber/**/*.rb
- library/fiber/**/*.rb
- optional/capi/fiber_spec.rb
Lint/RedundantSafeNavigation:
Exclude:
- language/safe_navigator_spec.rb
Lint/RedundantSplatExpansion:
Enabled: false
Lint/RescueException:
Enabled: false
Lint/UnifiedInteger:
Enabled: false

View File

@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2019-12-12 22:16:26 +0900 using RuboCop version 0.77.0.
# on 2024-10-12 16:01:45 UTC using RuboCop version 1.66.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@ -21,6 +21,7 @@ Lint/DuplicateMethods:
- 'fixtures/class.rb'
# Offense count: 8
# This cop supports safe autocorrection (--autocorrect).
Lint/EnsureReturn:
Exclude:
- 'language/fixtures/ensure.rb'
@ -39,6 +40,7 @@ Lint/FloatOutOfRange:
- 'core/string/modulo_spec.rb'
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
Lint/ImplicitStringConcatenation:
Exclude:
- 'language/string_spec.rb'
@ -50,8 +52,8 @@ Lint/IneffectiveAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'language/fixtures/private.rb'
# Offense count: 72
# Cop supports --auto-correct.
# Offense count: 71
# This cop supports safe autocorrection (--autocorrect).
Lint/LiteralInInterpolation:
Exclude:
- 'core/module/refine_spec.rb'
@ -65,47 +67,28 @@ Lint/LiteralInInterpolation:
- 'language/undef_spec.rb'
# Offense count: 8
# Cop supports --auto-correct.
# This cop supports safe autocorrection (--autocorrect).
Lint/MultipleComparison:
Exclude:
- 'language/precedence_spec.rb'
# Offense count: 9
# This cop supports safe autocorrection (--autocorrect).
Lint/ParenthesesAsGroupedExpression:
Exclude:
- 'core/string/fixtures/freeze_magic_comment.rb'
- 'language/block_spec.rb'
- 'language/fixtures/send.rb'
- 'language/method_spec.rb'
# Offense count: 2
# Cop supports --auto-correct.
# This cop supports safe autocorrection (--autocorrect).
Lint/RedundantStringCoercion:
Exclude:
- 'core/io/print_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
Lint/RedundantWithIndex:
Lint/SelfAssignment:
Exclude:
- 'core/enumerator/with_index_spec.rb'
# Offense count: 22
Lint/RescueException:
Exclude:
- 'command_line/fixtures/debug_info.rb'
- 'core/dir/fileno_spec.rb'
- 'core/exception/cause_spec.rb'
- 'core/exception/no_method_error_spec.rb'
- 'core/fiber/kill_spec.rb'
- 'core/kernel/fixtures/autoload_frozen.rb'
- 'core/kernel/raise_spec.rb'
- 'core/module/autoload_spec.rb'
- 'core/mutex/sleep_spec.rb'
- 'core/thread/abort_on_exception_spec.rb'
- 'core/thread/shared/exit.rb'
- 'language/rescue_spec.rb'
- 'library/erb/filename_spec.rb'
- 'core/gc/auto_compact_spec.rb'
# Offense count: 4
# Configuration parameters: IgnoreImplicitReferences.
@ -113,8 +96,8 @@ Lint/ShadowedArgument:
Exclude:
- 'language/fixtures/super.rb'
# Offense count: 39
# Configuration parameters: AllowComments.
# Offense count: 45
# Configuration parameters: AllowComments, AllowNil.
Lint/SuppressedException:
Enabled: false
@ -127,7 +110,8 @@ Lint/UnderscorePrefixedVariableName:
- 'language/block_spec.rb'
# Offense count: 7
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AutoCorrect, ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
- 'core/module/define_method_spec.rb'

View File

@ -179,7 +179,9 @@ In case there is a bug in MRI and the fix will be backported to previous version
If it is not backported or not likely, use `ruby_version_is` instead.
First, file a bug at https://bugs.ruby-lang.org/.
The problem is `ruby_bug` would make non-MRI implementations fail this spec while MRI itself does not pass it, so it should only be used if the bug is/will be fixed and backported.
Otherwise, non-MRI implementations would have to choose between being incompatible with the latest release of MRI to pass the spec or fail the spec, both which make no sense.
Otherwise, non-MRI implementations would have to choose between being incompatible with the latest release of MRI (which has the bug) to pass the spec, or behave the same as the latest release of MRI (which has the bug) and fail the spec, both which make no sense.
IOW, `ruby_bug '#NN', ''...'X.Y' do` is equivalent to `guard_not { RUBY_ENGINE == "ruby" && ruby_version_is ''...'X.Y' } do`. So it skips tests on MRI on specified versions (where a bug is present) and runs tests on alternative implementations only.
```ruby
ruby_bug '#13669', ''...'3.2' do

12
spec/ruby/bin/rubocop Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rubocop', '1.66.1'
end
exec(Gem.bin_path('rubocop', 'rubocop'), *ARGV)

View File

@ -22,15 +22,15 @@ describe "Processing RUBYOPT" do
result.should =~ /value of \$DEBUG is true/
end
guard -> { not CROSS_COMPILING } do
guard -> { RbConfig::CONFIG["CROSS_COMPILING"] != "yes" } do
it "prints the version number for '-v'" do
ENV["RUBYOPT"] = '-v'
ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
ruby_exe("").sub("+PRISM ", "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
end
it "ignores whitespace around the option" do
ENV["RUBYOPT"] = ' -v '
ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
ruby_exe("").sub("+PRISM ", "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
end
end

View File

@ -84,17 +84,17 @@ describe "BasicObject#instance_exec" do
end.should raise_error(TypeError)
end
quarantine! do # Not clean, leaves cvars lying around to break other specs
it "scopes class var accesses in the caller when called on an Integer" do
# Integer can take instance vars
Integer.class_eval "@@__tmp_instance_exec_spec = 1"
(defined? @@__tmp_instance_exec_spec).should == nil
quarantine! do # Not clean, leaves cvars lying around to break other specs
it "scopes class var accesses in the caller when called on an Integer" do
# Integer can take instance vars
Integer.class_eval "@@__tmp_instance_exec_spec = 1"
(defined? @@__tmp_instance_exec_spec).should == nil
@@__tmp_instance_exec_spec = 2
1.instance_exec { @@__tmp_instance_exec_spec }.should == 2
Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
@@__tmp_instance_exec_spec = 2
1.instance_exec { @@__tmp_instance_exec_spec }.should == 2
Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
end
end
end
it "raises a TypeError when defining methods on numerics" do
-> do

View File

@ -4,6 +4,10 @@ describe "RUBY_VERSION" do
it "is a String" do
RUBY_VERSION.should be_kind_of(String)
end
it "is frozen" do
RUBY_VERSION.should.frozen?
end
end
describe "RUBY_PATCHLEVEL" do
@ -16,34 +20,58 @@ describe "RUBY_COPYRIGHT" do
it "is a String" do
RUBY_COPYRIGHT.should be_kind_of(String)
end
it "is frozen" do
RUBY_COPYRIGHT.should.frozen?
end
end
describe "RUBY_DESCRIPTION" do
it "is a String" do
RUBY_DESCRIPTION.should be_kind_of(String)
end
it "is frozen" do
RUBY_DESCRIPTION.should.frozen?
end
end
describe "RUBY_ENGINE" do
it "is a String" do
RUBY_ENGINE.should be_kind_of(String)
end
it "is frozen" do
RUBY_ENGINE.should.frozen?
end
end
describe "RUBY_PLATFORM" do
it "is a String" do
RUBY_PLATFORM.should be_kind_of(String)
end
it "is frozen" do
RUBY_PLATFORM.should.frozen?
end
end
describe "RUBY_RELEASE_DATE" do
it "is a String" do
RUBY_RELEASE_DATE.should be_kind_of(String)
end
it "is frozen" do
RUBY_RELEASE_DATE.should.frozen?
end
end
describe "RUBY_REVISION" do
it "is a String" do
RUBY_REVISION.should be_kind_of(String)
end
it "is frozen" do
RUBY_REVISION.should.frozen?
end
end

View File

@ -76,7 +76,7 @@ describe "Complex#==" do
(Complex(real, 0) == @other).should be_true
end
it "returns false when when the imaginary part is not zero" do
it "returns false when the imaginary part is not zero" do
(Complex(3, 1) == @other).should be_false
end
end

View File

@ -0,0 +1,65 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
ruby_version_is "3.2" do
describe "Data#to_h" do
it "transforms the data object into a hash" do
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
data.to_h.should == { amount: 42, unit: 'km' }
end
context "with block" do
it "transforms [key, value] pairs returned by the block into a hash" do
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
data.to_h { |key, value| [value, key] }.should == { 42 => :amount, 'km' => :unit }
end
it "passes to a block each pair's key and value as separate arguments" do
ScratchPad.record []
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
data.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
ScratchPad.record []
data.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
end
it "raises ArgumentError if block returns longer or shorter array" do
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
-> do
data.to_h { |k, v| [k.to_s, v*v, 1] }
end.should raise_error(ArgumentError, /element has wrong array length/)
-> do
data.to_h { |k, v| [k] }
end.should raise_error(ArgumentError, /element has wrong array length/)
end
it "raises TypeError if block returns something other than Array" do
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
-> do
data.to_h { |k, v| "not-array" }
end.should raise_error(TypeError, /wrong element type String/)
end
it "coerces returned pair to Array with #to_ary" do
x = mock('x')
x.stub!(:to_ary).and_return([:b, 'b'])
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
data.to_h { |k| x }.should == { :b => 'b' }
end
it "does not coerce returned pair to Array with #to_a" do
x = mock('x')
x.stub!(:to_a).and_return([:b, 'b'])
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
-> do
data.to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject/)
end
end
end
end

View File

@ -161,6 +161,379 @@ describe "Encoding.compatible? String, String" do
Encoding.compatible?(@str, "").should == Encoding::UTF_7
end
end
# Encoding negotiation depends on whether encodings are ASCII-compatible, empty
# and contain only ASCII characters (that take 7 bits). Check US-ASCII, UTF-8 and
# BINARY encodings (as most common) as well as an ASCII-compatible, a non-ASCII-compatible and a dummy
# encodings in all possible combinations.
describe "compatibility matrix" do
# Use the following script to regenerate the matrix:
#
# ```
# # -*- encoding: binary -*-
#
# ENCODINGS = [
# "US-ASCII",
# "UTF-8",
# "ASCII-8BIT",
# "ISO-8859-1", # ASCII-compatible
# "UTF-16BE", # non-ASCII-compatible
# "ISO-2022-JP" # dummy
# ]
#
# TYPES = [:empty, :"7bits", :non7bits]
#
# VALUES = {
# empty: "",
# :"7bits" => "\x01",
# non7bits: "\x81"
# }
#
# ENCODINGS.product(TYPES, ENCODINGS, TYPES).each do |encoding1, type1, encoding2, type2|
# value1 = VALUES[type1].dup.force_encoding(encoding1)
# value2 = VALUES[type2].dup.force_encoding(encoding2)
#
# result_encoding = Encoding.compatible?(value1, value2)
#
# puts "[#{encoding1.inspect}, #{value1.inspect}, #{encoding2.inspect}, #{value2.inspect}, #{result_encoding&.name.inspect}],"
# end
# ```
matrix = [
["US-ASCII", "", "US-ASCII", "", "US-ASCII"],
["US-ASCII", "", "US-ASCII", "\x01", "US-ASCII"],
["US-ASCII", "", "US-ASCII", "\x81", "US-ASCII"],
["US-ASCII", "", "UTF-8", "", "US-ASCII"],
["US-ASCII", "", "UTF-8", "\u0001", "US-ASCII"],
["US-ASCII", "", "UTF-8", "\x81", "UTF-8"],
["US-ASCII", "", "ASCII-8BIT", "", "US-ASCII"],
["US-ASCII", "", "ASCII-8BIT", "\x01", "US-ASCII"],
["US-ASCII", "", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["US-ASCII", "", "ISO-8859-1", "", "US-ASCII"],
["US-ASCII", "", "ISO-8859-1", "\x01", "US-ASCII"],
["US-ASCII", "", "ISO-8859-1", "\x81", "ISO-8859-1"],
["US-ASCII", "", "UTF-16BE", "", "US-ASCII"],
["US-ASCII", "", "UTF-16BE", "\x01", "UTF-16BE"],
["US-ASCII", "", "UTF-16BE", "\x81", "UTF-16BE"],
["US-ASCII", "", "ISO-2022-JP", "", "US-ASCII"],
["US-ASCII", "", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["US-ASCII", "", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
["US-ASCII", "\x01", "US-ASCII", "", "US-ASCII"],
["US-ASCII", "\x01", "US-ASCII", "\x01", "US-ASCII"],
["US-ASCII", "\x01", "US-ASCII", "\x81", "US-ASCII"],
["US-ASCII", "\x01", "UTF-8", "", "US-ASCII"],
["US-ASCII", "\x01", "UTF-8", "\u0001", "US-ASCII"],
["US-ASCII", "\x01", "UTF-8", "\x81", "UTF-8"],
["US-ASCII", "\x01", "ASCII-8BIT", "", "US-ASCII"],
["US-ASCII", "\x01", "ASCII-8BIT", "\x01", "US-ASCII"],
["US-ASCII", "\x01", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["US-ASCII", "\x01", "ISO-8859-1", "", "US-ASCII"],
["US-ASCII", "\x01", "ISO-8859-1", "\x01", "US-ASCII"],
["US-ASCII", "\x01", "ISO-8859-1", "\x81", "ISO-8859-1"],
["US-ASCII", "\x01", "UTF-16BE", "", "US-ASCII"],
["US-ASCII", "\x01", "UTF-16BE", "\x01", nil],
["US-ASCII", "\x01", "UTF-16BE", "\x81", nil],
["US-ASCII", "\x01", "ISO-2022-JP", "", "US-ASCII"],
["US-ASCII", "\x01", "ISO-2022-JP", "\x01", nil],
["US-ASCII", "\x01", "ISO-2022-JP", "\x81", nil],
["US-ASCII", "\x81", "US-ASCII", "", "US-ASCII"],
["US-ASCII", "\x81", "US-ASCII", "\x01", "US-ASCII"],
["US-ASCII", "\x81", "US-ASCII", "\x81", "US-ASCII"],
["US-ASCII", "\x81", "UTF-8", "", "US-ASCII"],
["US-ASCII", "\x81", "UTF-8", "\u0001", "US-ASCII"],
["US-ASCII", "\x81", "UTF-8", "\x81", nil],
["US-ASCII", "\x81", "ASCII-8BIT", "", "US-ASCII"],
["US-ASCII", "\x81", "ASCII-8BIT", "\x01", "US-ASCII"],
["US-ASCII", "\x81", "ASCII-8BIT", "\x81", nil],
["US-ASCII", "\x81", "ISO-8859-1", "", "US-ASCII"],
["US-ASCII", "\x81", "ISO-8859-1", "\x01", "US-ASCII"],
["US-ASCII", "\x81", "ISO-8859-1", "\x81", nil],
["US-ASCII", "\x81", "UTF-16BE", "", "US-ASCII"],
["US-ASCII", "\x81", "UTF-16BE", "\x01", nil],
["US-ASCII", "\x81", "UTF-16BE", "\x81", nil],
["US-ASCII", "\x81", "ISO-2022-JP", "", "US-ASCII"],
["US-ASCII", "\x81", "ISO-2022-JP", "\x01", nil],
["US-ASCII", "\x81", "ISO-2022-JP", "\x81", nil],
["UTF-8", "", "US-ASCII", "", "UTF-8"],
["UTF-8", "", "US-ASCII", "\x01", "UTF-8"],
["UTF-8", "", "US-ASCII", "\x81", "US-ASCII"],
["UTF-8", "", "UTF-8", "", "UTF-8"],
["UTF-8", "", "UTF-8", "\u0001", "UTF-8"],
["UTF-8", "", "UTF-8", "\x81", "UTF-8"],
["UTF-8", "", "ASCII-8BIT", "", "UTF-8"],
["UTF-8", "", "ASCII-8BIT", "\x01", "UTF-8"],
["UTF-8", "", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["UTF-8", "", "ISO-8859-1", "", "UTF-8"],
["UTF-8", "", "ISO-8859-1", "\x01", "UTF-8"],
["UTF-8", "", "ISO-8859-1", "\x81", "ISO-8859-1"],
["UTF-8", "", "UTF-16BE", "", "UTF-8"],
["UTF-8", "", "UTF-16BE", "\x01", "UTF-16BE"],
["UTF-8", "", "UTF-16BE", "\x81", "UTF-16BE"],
["UTF-8", "", "ISO-2022-JP", "", "UTF-8"],
["UTF-8", "", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["UTF-8", "", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
["UTF-8", "\u0001", "US-ASCII", "", "UTF-8"],
["UTF-8", "\u0001", "US-ASCII", "\x01", "UTF-8"],
["UTF-8", "\u0001", "US-ASCII", "\x81", "US-ASCII"],
["UTF-8", "\u0001", "UTF-8", "", "UTF-8"],
["UTF-8", "\u0001", "UTF-8", "\u0001", "UTF-8"],
["UTF-8", "\u0001", "UTF-8", "\x81", "UTF-8"],
["UTF-8", "\u0001", "ASCII-8BIT", "", "UTF-8"],
["UTF-8", "\u0001", "ASCII-8BIT", "\x01", "UTF-8"],
["UTF-8", "\u0001", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["UTF-8", "\u0001", "ISO-8859-1", "", "UTF-8"],
["UTF-8", "\u0001", "ISO-8859-1", "\x01", "UTF-8"],
["UTF-8", "\u0001", "ISO-8859-1", "\x81", "ISO-8859-1"],
["UTF-8", "\u0001", "UTF-16BE", "", "UTF-8"],
["UTF-8", "\u0001", "UTF-16BE", "\x01", nil],
["UTF-8", "\u0001", "UTF-16BE", "\x81", nil],
["UTF-8", "\u0001", "ISO-2022-JP", "", "UTF-8"],
["UTF-8", "\u0001", "ISO-2022-JP", "\x01", nil],
["UTF-8", "\u0001", "ISO-2022-JP", "\x81", nil],
["UTF-8", "\x81", "US-ASCII", "", "UTF-8"],
["UTF-8", "\x81", "US-ASCII", "\x01", "UTF-8"],
["UTF-8", "\x81", "US-ASCII", "\x81", nil],
["UTF-8", "\x81", "UTF-8", "", "UTF-8"],
["UTF-8", "\x81", "UTF-8", "\u0001", "UTF-8"],
["UTF-8", "\x81", "UTF-8", "\x81", "UTF-8"],
["UTF-8", "\x81", "ASCII-8BIT", "", "UTF-8"],
["UTF-8", "\x81", "ASCII-8BIT", "\x01", "UTF-8"],
["UTF-8", "\x81", "ASCII-8BIT", "\x81", nil],
["UTF-8", "\x81", "ISO-8859-1", "", "UTF-8"],
["UTF-8", "\x81", "ISO-8859-1", "\x01", "UTF-8"],
["UTF-8", "\x81", "ISO-8859-1", "\x81", nil],
["UTF-8", "\x81", "UTF-16BE", "", "UTF-8"],
["UTF-8", "\x81", "UTF-16BE", "\x01", nil],
["UTF-8", "\x81", "UTF-16BE", "\x81", nil],
["UTF-8", "\x81", "ISO-2022-JP", "", "UTF-8"],
["UTF-8", "\x81", "ISO-2022-JP", "\x01", nil],
["UTF-8", "\x81", "ISO-2022-JP", "\x81", nil],
["ASCII-8BIT", "", "US-ASCII", "", "ASCII-8BIT"],
["ASCII-8BIT", "", "US-ASCII", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "", "US-ASCII", "\x81", "US-ASCII"],
["ASCII-8BIT", "", "UTF-8", "", "ASCII-8BIT"],
["ASCII-8BIT", "", "UTF-8", "\u0001", "ASCII-8BIT"],
["ASCII-8BIT", "", "UTF-8", "\x81", "UTF-8"],
["ASCII-8BIT", "", "ASCII-8BIT", "", "ASCII-8BIT"],
["ASCII-8BIT", "", "ASCII-8BIT", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["ASCII-8BIT", "", "ISO-8859-1", "", "ASCII-8BIT"],
["ASCII-8BIT", "", "ISO-8859-1", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "", "ISO-8859-1", "\x81", "ISO-8859-1"],
["ASCII-8BIT", "", "UTF-16BE", "", "ASCII-8BIT"],
["ASCII-8BIT", "", "UTF-16BE", "\x01", "UTF-16BE"],
["ASCII-8BIT", "", "UTF-16BE", "\x81", "UTF-16BE"],
["ASCII-8BIT", "", "ISO-2022-JP", "", "ASCII-8BIT"],
["ASCII-8BIT", "", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["ASCII-8BIT", "", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
["ASCII-8BIT", "\x01", "US-ASCII", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "US-ASCII", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "US-ASCII", "\x81", "US-ASCII"],
["ASCII-8BIT", "\x01", "UTF-8", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "UTF-8", "\u0001", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "UTF-8", "\x81", "UTF-8"],
["ASCII-8BIT", "\x01", "ASCII-8BIT", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "ASCII-8BIT", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "ISO-8859-1", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "ISO-8859-1", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "ISO-8859-1", "\x81", "ISO-8859-1"],
["ASCII-8BIT", "\x01", "UTF-16BE", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "UTF-16BE", "\x01", nil],
["ASCII-8BIT", "\x01", "UTF-16BE", "\x81", nil],
["ASCII-8BIT", "\x01", "ISO-2022-JP", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x01", "ISO-2022-JP", "\x01", nil],
["ASCII-8BIT", "\x01", "ISO-2022-JP", "\x81", nil],
["ASCII-8BIT", "\x81", "US-ASCII", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "US-ASCII", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "US-ASCII", "\x81", nil],
["ASCII-8BIT", "\x81", "UTF-8", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "UTF-8", "\u0001", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "UTF-8", "\x81", nil],
["ASCII-8BIT", "\x81", "ASCII-8BIT", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "ASCII-8BIT", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "ISO-8859-1", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "ISO-8859-1", "\x01", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "ISO-8859-1", "\x81", nil],
["ASCII-8BIT", "\x81", "UTF-16BE", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "UTF-16BE", "\x01", nil],
["ASCII-8BIT", "\x81", "UTF-16BE", "\x81", nil],
["ASCII-8BIT", "\x81", "ISO-2022-JP", "", "ASCII-8BIT"],
["ASCII-8BIT", "\x81", "ISO-2022-JP", "\x01", nil],
["ASCII-8BIT", "\x81", "ISO-2022-JP", "\x81", nil],
["ISO-8859-1", "", "US-ASCII", "", "ISO-8859-1"],
["ISO-8859-1", "", "US-ASCII", "\x01", "ISO-8859-1"],
["ISO-8859-1", "", "US-ASCII", "\x81", "US-ASCII"],
["ISO-8859-1", "", "UTF-8", "", "ISO-8859-1"],
["ISO-8859-1", "", "UTF-8", "\u0001", "ISO-8859-1"],
["ISO-8859-1", "", "UTF-8", "\x81", "UTF-8"],
["ISO-8859-1", "", "ASCII-8BIT", "", "ISO-8859-1"],
["ISO-8859-1", "", "ASCII-8BIT", "\x01", "ISO-8859-1"],
["ISO-8859-1", "", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["ISO-8859-1", "", "ISO-8859-1", "", "ISO-8859-1"],
["ISO-8859-1", "", "ISO-8859-1", "\x01", "ISO-8859-1"],
["ISO-8859-1", "", "ISO-8859-1", "\x81", "ISO-8859-1"],
["ISO-8859-1", "", "UTF-16BE", "", "ISO-8859-1"],
["ISO-8859-1", "", "UTF-16BE", "\x01", "UTF-16BE"],
["ISO-8859-1", "", "UTF-16BE", "\x81", "UTF-16BE"],
["ISO-8859-1", "", "ISO-2022-JP", "", "ISO-8859-1"],
["ISO-8859-1", "", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["ISO-8859-1", "", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
["ISO-8859-1", "\x01", "US-ASCII", "", "ISO-8859-1"],
["ISO-8859-1", "\x01", "US-ASCII", "\x01", "ISO-8859-1"],
["ISO-8859-1", "\x01", "US-ASCII", "\x81", "US-ASCII"],
["ISO-8859-1", "\x01", "UTF-8", "", "ISO-8859-1"],
["ISO-8859-1", "\x01", "UTF-8", "\u0001", "ISO-8859-1"],
["ISO-8859-1", "\x01", "UTF-8", "\x81", "UTF-8"],
["ISO-8859-1", "\x01", "ASCII-8BIT", "", "ISO-8859-1"],
["ISO-8859-1", "\x01", "ASCII-8BIT", "\x01", "ISO-8859-1"],
["ISO-8859-1", "\x01", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["ISO-8859-1", "\x01", "ISO-8859-1", "", "ISO-8859-1"],
["ISO-8859-1", "\x01", "ISO-8859-1", "\x01", "ISO-8859-1"],
["ISO-8859-1", "\x01", "ISO-8859-1", "\x81", "ISO-8859-1"],
["ISO-8859-1", "\x01", "UTF-16BE", "", "ISO-8859-1"],
["ISO-8859-1", "\x01", "UTF-16BE", "\x01", nil],
["ISO-8859-1", "\x01", "UTF-16BE", "\x81", nil],
["ISO-8859-1", "\x01", "ISO-2022-JP", "", "ISO-8859-1"],
["ISO-8859-1", "\x01", "ISO-2022-JP", "\x01", nil],
["ISO-8859-1", "\x01", "ISO-2022-JP", "\x81", nil],
["ISO-8859-1", "\x81", "US-ASCII", "", "ISO-8859-1"],
["ISO-8859-1", "\x81", "US-ASCII", "\x01", "ISO-8859-1"],
["ISO-8859-1", "\x81", "US-ASCII", "\x81", nil],
["ISO-8859-1", "\x81", "UTF-8", "", "ISO-8859-1"],
["ISO-8859-1", "\x81", "UTF-8", "\u0001", "ISO-8859-1"],
["ISO-8859-1", "\x81", "UTF-8", "\x81", nil],
["ISO-8859-1", "\x81", "ASCII-8BIT", "", "ISO-8859-1"],
["ISO-8859-1", "\x81", "ASCII-8BIT", "\x01", "ISO-8859-1"],
["ISO-8859-1", "\x81", "ASCII-8BIT", "\x81", nil],
["ISO-8859-1", "\x81", "ISO-8859-1", "", "ISO-8859-1"],
["ISO-8859-1", "\x81", "ISO-8859-1", "\x01", "ISO-8859-1"],
["ISO-8859-1", "\x81", "ISO-8859-1", "\x81", "ISO-8859-1"],
["ISO-8859-1", "\x81", "UTF-16BE", "", "ISO-8859-1"],
["ISO-8859-1", "\x81", "UTF-16BE", "\x01", nil],
["ISO-8859-1", "\x81", "UTF-16BE", "\x81", nil],
["ISO-8859-1", "\x81", "ISO-2022-JP", "", "ISO-8859-1"],
["ISO-8859-1", "\x81", "ISO-2022-JP", "\x01", nil],
["ISO-8859-1", "\x81", "ISO-2022-JP", "\x81", nil],
["UTF-16BE", "", "US-ASCII", "", "UTF-16BE"],
["UTF-16BE", "", "US-ASCII", "\x01", "US-ASCII"],
["UTF-16BE", "", "US-ASCII", "\x81", "US-ASCII"],
["UTF-16BE", "", "UTF-8", "", "UTF-16BE"],
["UTF-16BE", "", "UTF-8", "\u0001", "UTF-8"],
["UTF-16BE", "", "UTF-8", "\x81", "UTF-8"],
["UTF-16BE", "", "ASCII-8BIT", "", "UTF-16BE"],
["UTF-16BE", "", "ASCII-8BIT", "\x01", "ASCII-8BIT"],
["UTF-16BE", "", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["UTF-16BE", "", "ISO-8859-1", "", "UTF-16BE"],
["UTF-16BE", "", "ISO-8859-1", "\x01", "ISO-8859-1"],
["UTF-16BE", "", "ISO-8859-1", "\x81", "ISO-8859-1"],
["UTF-16BE", "", "UTF-16BE", "", "UTF-16BE"],
["UTF-16BE", "", "UTF-16BE", "\x01", "UTF-16BE"],
["UTF-16BE", "", "UTF-16BE", "\x81", "UTF-16BE"],
["UTF-16BE", "", "ISO-2022-JP", "", "UTF-16BE"],
["UTF-16BE", "", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["UTF-16BE", "", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
["UTF-16BE", "\x01", "US-ASCII", "", "UTF-16BE"],
["UTF-16BE", "\x01", "US-ASCII", "\x01", nil],
["UTF-16BE", "\x01", "US-ASCII", "\x81", nil],
["UTF-16BE", "\x01", "UTF-8", "", "UTF-16BE"],
["UTF-16BE", "\x01", "UTF-8", "\u0001", nil],
["UTF-16BE", "\x01", "UTF-8", "\x81", nil],
["UTF-16BE", "\x01", "ASCII-8BIT", "", "UTF-16BE"],
["UTF-16BE", "\x01", "ASCII-8BIT", "\x01", nil],
["UTF-16BE", "\x01", "ASCII-8BIT", "\x81", nil],
["UTF-16BE", "\x01", "ISO-8859-1", "", "UTF-16BE"],
["UTF-16BE", "\x01", "ISO-8859-1", "\x01", nil],
["UTF-16BE", "\x01", "ISO-8859-1", "\x81", nil],
["UTF-16BE", "\x01", "UTF-16BE", "", "UTF-16BE"],
["UTF-16BE", "\x01", "UTF-16BE", "\x01", "UTF-16BE"],
["UTF-16BE", "\x01", "UTF-16BE", "\x81", "UTF-16BE"],
["UTF-16BE", "\x01", "ISO-2022-JP", "", "UTF-16BE"],
["UTF-16BE", "\x01", "ISO-2022-JP", "\x01", nil],
["UTF-16BE", "\x01", "ISO-2022-JP", "\x81", nil],
["UTF-16BE", "\x81", "US-ASCII", "", "UTF-16BE"],
["UTF-16BE", "\x81", "US-ASCII", "\x01", nil],
["UTF-16BE", "\x81", "US-ASCII", "\x81", nil],
["UTF-16BE", "\x81", "UTF-8", "", "UTF-16BE"],
["UTF-16BE", "\x81", "UTF-8", "\u0001", nil],
["UTF-16BE", "\x81", "UTF-8", "\x81", nil],
["UTF-16BE", "\x81", "ASCII-8BIT", "", "UTF-16BE"],
["UTF-16BE", "\x81", "ASCII-8BIT", "\x01", nil],
["UTF-16BE", "\x81", "ASCII-8BIT", "\x81", nil],
["UTF-16BE", "\x81", "ISO-8859-1", "", "UTF-16BE"],
["UTF-16BE", "\x81", "ISO-8859-1", "\x01", nil],
["UTF-16BE", "\x81", "ISO-8859-1", "\x81", nil],
["UTF-16BE", "\x81", "UTF-16BE", "", "UTF-16BE"],
["UTF-16BE", "\x81", "UTF-16BE", "\x01", "UTF-16BE"],
["UTF-16BE", "\x81", "UTF-16BE", "\x81", "UTF-16BE"],
["UTF-16BE", "\x81", "ISO-2022-JP", "", "UTF-16BE"],
["UTF-16BE", "\x81", "ISO-2022-JP", "\x01", nil],
["UTF-16BE", "\x81", "ISO-2022-JP", "\x81", nil],
["ISO-2022-JP", "", "US-ASCII", "", "ISO-2022-JP"],
["ISO-2022-JP", "", "US-ASCII", "\x01", "US-ASCII"],
["ISO-2022-JP", "", "US-ASCII", "\x81", "US-ASCII"],
["ISO-2022-JP", "", "UTF-8", "", "ISO-2022-JP"],
["ISO-2022-JP", "", "UTF-8", "\u0001", "UTF-8"],
["ISO-2022-JP", "", "UTF-8", "\x81", "UTF-8"],
["ISO-2022-JP", "", "ASCII-8BIT", "", "ISO-2022-JP"],
["ISO-2022-JP", "", "ASCII-8BIT", "\x01", "ASCII-8BIT"],
["ISO-2022-JP", "", "ASCII-8BIT", "\x81", "ASCII-8BIT"],
["ISO-2022-JP", "", "ISO-8859-1", "", "ISO-2022-JP"],
["ISO-2022-JP", "", "ISO-8859-1", "\x01", "ISO-8859-1"],
["ISO-2022-JP", "", "ISO-8859-1", "\x81", "ISO-8859-1"],
["ISO-2022-JP", "", "UTF-16BE", "", "ISO-2022-JP"],
["ISO-2022-JP", "", "UTF-16BE", "\x01", "UTF-16BE"],
["ISO-2022-JP", "", "UTF-16BE", "\x81", "UTF-16BE"],
["ISO-2022-JP", "", "ISO-2022-JP", "", "ISO-2022-JP"],
["ISO-2022-JP", "", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["ISO-2022-JP", "", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "US-ASCII", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "US-ASCII", "\x01", nil],
["ISO-2022-JP", "\x01", "US-ASCII", "\x81", nil],
["ISO-2022-JP", "\x01", "UTF-8", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "UTF-8", "\u0001", nil],
["ISO-2022-JP", "\x01", "UTF-8", "\x81", nil],
["ISO-2022-JP", "\x01", "ASCII-8BIT", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "ASCII-8BIT", "\x01", nil],
["ISO-2022-JP", "\x01", "ASCII-8BIT", "\x81", nil],
["ISO-2022-JP", "\x01", "ISO-8859-1", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "ISO-8859-1", "\x01", nil],
["ISO-2022-JP", "\x01", "ISO-8859-1", "\x81", nil],
["ISO-2022-JP", "\x01", "UTF-16BE", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "UTF-16BE", "\x01", nil],
["ISO-2022-JP", "\x01", "UTF-16BE", "\x81", nil],
["ISO-2022-JP", "\x01", "ISO-2022-JP", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["ISO-2022-JP", "\x01", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "US-ASCII", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "US-ASCII", "\x01", nil],
["ISO-2022-JP", "\x81", "US-ASCII", "\x81", nil],
["ISO-2022-JP", "\x81", "UTF-8", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "UTF-8", "\u0001", nil],
["ISO-2022-JP", "\x81", "UTF-8", "\x81", nil],
["ISO-2022-JP", "\x81", "ASCII-8BIT", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "ASCII-8BIT", "\x01", nil],
["ISO-2022-JP", "\x81", "ASCII-8BIT", "\x81", nil],
["ISO-2022-JP", "\x81", "ISO-8859-1", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "ISO-8859-1", "\x01", nil],
["ISO-2022-JP", "\x81", "ISO-8859-1", "\x81", nil],
["ISO-2022-JP", "\x81", "UTF-16BE", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "UTF-16BE", "\x01", nil],
["ISO-2022-JP", "\x81", "UTF-16BE", "\x81", nil],
["ISO-2022-JP", "\x81", "ISO-2022-JP", "", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "ISO-2022-JP", "\x01", "ISO-2022-JP"],
["ISO-2022-JP", "\x81", "ISO-2022-JP", "\x81", "ISO-2022-JP"],
]
matrix.each do |encoding1, value1, encoding2, value2, compatible_encoding|
it "returns #{compatible_encoding} for #{value1.inspect} in #{encoding1} and #{value2.inspect} in #{encoding2}" do
actual_encoding = Encoding.compatible?(value1.dup.force_encoding(encoding1), value2.dup.force_encoding(encoding2))
actual_encoding&.name.should == compatible_encoding
end
end
end
end
describe "Encoding.compatible? String, Regexp" do
@ -377,3 +750,9 @@ describe "Encoding.compatible? Object, Object" do
Encoding.compatible?(:sym, Object.new).should be_nil
end
end
describe "Encoding.compatible? nil, nil" do
it "returns nil" do
Encoding.compatible?(nil, nil).should be_nil
end
end

View File

@ -21,16 +21,16 @@ describe "Enumerator#each_with_index" do
it "passes on the given block's return value" do
arr = [1,2,3]
arr.delete_if.with_index { |a,b| false }
arr.delete_if.each_with_index { |a,b| false }
arr.should == [1,2,3]
end
it "returns the iterator's return value" do
[1,2,3].select.with_index { |a,b| false }.should == []
[1,2,3].select.each_with_index { |a,b| false }.should == []
[1,2,3].select.each_with_index { |a,b| true }.should == [1,2,3]
end
it "returns the correct value if chained with itself" do
[:a].each_with_index.each_with_index.to_a.should == [[[:a,0],0]]
[:a].each.with_index.with_index.to_a.should == [[[:a,0],0]]
end
end

View File

@ -69,4 +69,21 @@ describe "Enumerator#with_index" do
@enum.with_index(-1) { |*x| res << x}
res.should == [[1,-1], [2,0], [3,1], [4,2]]
end
it "passes on the given block's return value" do
arr = [1,2,3]
arr.delete_if.with_index { |a,b| false }
arr.should == [1,2,3]
arr.delete_if.with_index { |a,b| true }
arr.should == []
end
it "returns the iterator's return value" do
@enum.select.with_index { |a,b| false }.should == []
end
it "returns the correct value if chained with itself" do
[:a].each.with_index.with_index.to_a.should == [[[:a,0],0]]
end
end

View File

@ -79,6 +79,24 @@ describe "Exception#full_message" do
err.full_message(highlight: true).should !~ /unhandled exception/
err.full_message(highlight: false).should !~ /unhandled exception/
end
it "adds escape sequences to highlight some strings if the message is not specified and :highlight option is specified" do
e = RuntimeError.new("")
full_message = e.full_message(highlight: true, order: :top).lines
full_message[0].should.end_with? "\e[1;4munhandled exception\e[m\n"
full_message = e.full_message(highlight: true, order: :bottom).lines
full_message[0].should == "\e[1mTraceback\e[m (most recent call last):\n"
full_message[-1].should.end_with? "\e[1;4munhandled exception\e[m\n"
full_message = e.full_message(highlight: false, order: :top).lines
full_message[0].should.end_with? "unhandled exception\n"
full_message = e.full_message(highlight: false, order: :bottom).lines
full_message[0].should == "Traceback (most recent call last):\n"
full_message[-1].should.end_with? "unhandled exception\n"
end
end
describe "generic Error" do

View File

@ -42,7 +42,7 @@ describe "Fiber#raise" do
-> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error' }.should raise_error(FiberSpecs::CustomError, 'test error')
end
it 'accepts error class with with error message and backtrace information' do
it 'accepts error class with error message and backtrace information' do
-> {
FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error', ['foo', 'boo']
}.should raise_error(FiberSpecs::CustomError) { |e|

View File

@ -78,15 +78,15 @@ describe "File.chown" do
end
describe "File#chown" do
before :each do
@fname = tmp('file_chown_test')
@file = File.open(@fname, 'w')
end
before :each do
@fname = tmp('file_chown_test')
@file = File.open(@fname, 'w')
end
after :each do
@file.close unless @file.closed?
rm_r @fname
end
after :each do
@file.close unless @file.closed?
rm_r @fname
end
as_superuser do
platform_is :windows do

View File

@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../integer/shared/integer_ceil_precision'
describe "Float#ceil" do
context "with precision" do
it_behaves_like :integer_ceil_precision, :Float
end
it "returns the smallest Integer greater than or equal to self" do
-1.2.ceil.should eql( -1)
-1.0.ceil.should eql( -1)

View File

@ -72,7 +72,7 @@ describe "Float#<=>" do
(-Float::MAX.to_i*2 <=> -infinity_value).should == 1
end
it "returns 0 when self is Infinity and other other is infinite?=1" do
it "returns 0 when self is Infinity and other is infinite?=1" do
obj = Object.new
def obj.infinite?
1

View File

@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../integer/shared/integer_floor_precision'
describe "Float#floor" do
context "with precision" do
it_behaves_like :integer_floor_precision, :Float
end
it "returns the largest Integer less than or equal to self" do
-1.2.floor.should eql( -2)
-1.0.floor.should eql( -1)

View File

@ -12,7 +12,7 @@ describe "Hash#[]" do
h[[]].should == "baz"
end
it "returns nil as default default value" do
it "returns nil as default value" do
{ 0 => 0 }[5].should == nil
end

View File

@ -47,7 +47,7 @@ describe "Hash#hash" do
a = 1
b = 2
eval('{a:, b:}.should == { a: 1, b: 2 }')
eval('{a:, b:}.should == { a: 1, b: 2 }')
end
end
end

View File

@ -1,11 +1,16 @@
require_relative '../../spec_helper'
require_relative 'shared/to_i'
require_relative 'shared/integer_rounding'
require_relative 'shared/integer_ceil_precision'
describe "Integer#ceil" do
it_behaves_like :integer_to_i, :ceil
it_behaves_like :integer_rounding_positive_precision, :ceil
context "with precision" do
it_behaves_like :integer_ceil_precision, :Integer
end
context "precision argument specified as part of the ceil method is negative" do
it "returns the smallest integer greater than self with at least precision.abs trailing zeros" do
18.ceil(-1).should eql(20)

View File

@ -1,19 +1,13 @@
require_relative '../../spec_helper'
require_relative 'shared/to_i'
require_relative 'shared/integer_rounding'
require_relative 'shared/integer_floor_precision'
describe "Integer#floor" do
it_behaves_like :integer_to_i, :floor
it_behaves_like :integer_rounding_positive_precision, :floor
context "precision argument specified as part of the floor method is negative" do
it "returns the largest integer less than self with at least precision.abs trailing zeros" do
1832.floor(-1).should eql(1830)
1832.floor(-2).should eql(1800)
1832.floor(-3).should eql(1000)
-1832.floor(-1).should eql(-1840)
-1832.floor(-2).should eql(-1900)
-1832.floor(-3).should eql(-2000)
end
context "with precision" do
it_behaves_like :integer_floor_precision, :Integer
end
end

View File

@ -19,13 +19,13 @@ describe "Integer#pow" do
2.pow(61, 5843009213693951).should eql 3697379018277258
2.pow(62, 5843009213693952).should eql 1551748822859776
2.pow(63, 5843009213693953).should eql 3103497645717974
2.pow(64, 5843009213693954).should eql 363986077738838
2.pow(64, 5843009213693954).should eql 363986077738838
end
it "handles sign like #divmod does" do
2.pow(5, 12).should == 8
2.pow(5, -12).should == -4
-2.pow(5, 12).should == 4
2.pow(5, 12).should == 8
2.pow(5, -12).should == -4
-2.pow(5, 12).should == 4
-2.pow(5, -12).should == -8
end

View File

@ -15,8 +15,8 @@ describe "Integer#remainder" do
end
it "keeps sign of self" do
5.remainder( 3).should == 2
5.remainder(-3).should == 2
5.remainder( 3).should == 2
5.remainder(-3).should == 2
-5.remainder( 3).should == -2
-5.remainder(-3).should == -2
end

View File

@ -0,0 +1,43 @@
describe :integer_ceil_precision, shared: true do
context "precision is zero" do
it "returns integer self" do
send(@method, 0).ceil(0).should.eql?(0)
send(@method, 123).ceil(0).should.eql?(123)
send(@method, -123).ceil(0).should.eql?(-123)
end
end
context "precision is positive" do
it "returns self" do
send(@method, 0).ceil(1).should.eql?(send(@method, 0))
send(@method, 0).ceil(10).should.eql?(send(@method, 0))
send(@method, 123).ceil(10).should.eql?(send(@method, 123))
send(@method, -123).ceil(10).should.eql?(send(@method, -123))
end
end
context "precision is negative" do
it "always returns 0 when self is 0" do
send(@method, 0).ceil(-1).should.eql?(0)
send(@method, 0).ceil(-10).should.eql?(0)
end
it "returns largest integer less than self with at least precision.abs trailing zeros" do
send(@method, 123).ceil(-1).should.eql?(130)
send(@method, 123).ceil(-2).should.eql?(200)
send(@method, 123).ceil(-3).should.eql?(1000)
send(@method, -123).ceil(-1).should.eql?(-120)
send(@method, -123).ceil(-2).should.eql?(-100)
send(@method, -123).ceil(-3).should.eql?(0)
end
ruby_bug "#20654", ""..."3.4" do
it "returns 10**precision.abs when precision.abs is larger than the number digits of self" do
send(@method, 123).ceil(-20).should.eql?(100000000000000000000)
send(@method, 123).ceil(-50).should.eql?(100000000000000000000000000000000000000000000000000)
end
end
end
end

View File

@ -0,0 +1,43 @@
describe :integer_floor_precision, shared: true do
context "precision is zero" do
it "returns integer self" do
send(@method, 0).floor(0).should.eql?(0)
send(@method, 123).floor(0).should.eql?(123)
send(@method, -123).floor(0).should.eql?(-123)
end
end
context "precision is positive" do
it "returns self" do
send(@method, 0).floor(1).should.eql?(send(@method, 0))
send(@method, 0).floor(10).should.eql?(send(@method, 0))
send(@method, 123).floor(10).should.eql?(send(@method, 123))
send(@method, -123).floor(10).should.eql?(send(@method, -123))
end
end
context "precision is negative" do
it "always returns 0 when self is 0" do
send(@method, 0).floor(-1).should.eql?(0)
send(@method, 0).floor(-10).should.eql?(0)
end
it "returns largest integer less than self with at least precision.abs trailing zeros" do
send(@method, 123).floor(-1).should.eql?(120)
send(@method, 123).floor(-2).should.eql?(100)
send(@method, 123).floor(-3).should.eql?(0)
send(@method, -123).floor(-1).should.eql?(-130)
send(@method, -123).floor(-2).should.eql?(-200)
send(@method, -123).floor(-3).should.eql?(-1000)
end
ruby_bug "#20654", ""..."3.4" do
it "returns -(10**precision.abs) when self is negative and precision.abs is larger than the number digits of self" do
send(@method, -123).floor(-20).should.eql?(-100000000000000000000)
send(@method, -123).floor(-50).should.eql?(-100000000000000000000000000000000000000000000000000)
end
end
end
end

View File

@ -25,27 +25,27 @@ describe "IO#dup" do
@i.fileno.should_not == @f.fileno
end
quarantine! do # This does not appear to be consistent across platforms
it "shares the original stream between the two IOs" do
start = @f.pos
@i.pos.should == start
quarantine! do # This does not appear to be consistent across platforms
it "shares the original stream between the two IOs" do
start = @f.pos
@i.pos.should == start
s = "Hello, wo.. wait, where am I?\n"
s2 = "<evil voice> Muhahahaa!"
s = "Hello, wo.. wait, where am I?\n"
s2 = "<evil voice> Muhahahaa!"
@f.write s
@i.pos.should == @f.pos
@f.write s
@i.pos.should == @f.pos
@i.rewind
@i.gets.should == s
@i.rewind
@i.gets.should == s
@i.rewind
@i.write s2
@i.rewind
@i.write s2
@f.rewind
@f.gets.should == "#{s2}\n"
@f.rewind
@f.gets.should == "#{s2}\n"
end
end
end
it "allows closing the new IO without affecting the original" do
@i.close

View File

@ -33,7 +33,7 @@ describe "IO#puts" do
ScratchPad.recorded.should == "\n"
end
it "writes empty string with a newline when when given nil as multiple args" do
it "writes empty string with a newline when given nil as multiple args" do
@io.puts(nil, nil).should == nil
ScratchPad.recorded.should == "\n\n"
end

View File

@ -217,19 +217,19 @@ describe "IO.read from a pipe" do
end
end
quarantine! do # The process tried to write to a nonexistent pipe.
platform_is :windows do
# TODO: It should raise Errno::ESPIPE on Windows as well
# once https://bugs.ruby-lang.org/issues/12230 is fixed.
it "raises Errno::EINVAL if passed an offset" do
-> {
suppress_warning do # https://bugs.ruby-lang.org/issues/19630
IO.read("|cmd.exe /C echo hello", 1, 1)
end
}.should raise_error(Errno::EINVAL)
quarantine! do # The process tried to write to a nonexistent pipe.
platform_is :windows do
# TODO: It should raise Errno::ESPIPE on Windows as well
# once https://bugs.ruby-lang.org/issues/12230 is fixed.
it "raises Errno::EINVAL if passed an offset" do
-> {
suppress_warning do # https://bugs.ruby-lang.org/issues/19630
IO.read("|cmd.exe /C echo hello", 1, 1)
end
}.should raise_error(Errno::EINVAL)
end
end
end
end
ruby_version_is "3.3" do
# https://bugs.ruby-lang.org/issues/19630

View File

@ -274,6 +274,26 @@ describe "Kernel#eval" do
eval("").should == nil
end
context "with shebang" do
it "ignores shebang with ruby interpreter" do
pid = eval(<<~CODE.b)
#!/usr/bin/env ruby
Process.pid
CODE
pid.should == Process.pid
end
it "ignores shebang with non-ruby interpreter" do
pid = eval(<<~CODE.b)
#!/usr/bin/env puma
Process.pid
CODE
pid.should == Process.pid
end
end
# See language/magic_comment_spec.rb for more magic comments specs
describe "with a magic encoding comment" do
it "uses the magic comment encoding for the encoding of literal strings" do

View File

@ -76,4 +76,16 @@ describe "Kernel#extend" do
-> { @frozen.extend @module }.should raise_error(FrozenError)
end
end
it "updated class methods of a module when it extends self and includes another module" do
a = Module.new do
extend self
end
b = Module.new do
def foo; :foo; end
end
a.include b
a.foo.should == :foo
end
end

View File

@ -46,6 +46,22 @@ describe "Kernel#raise" do
cause = StandardError.new
-> { raise(cause: cause) }.should raise_error(ArgumentError)
end
it "re-raises a rescued exception" do
-> do
begin
raise StandardError, "aaa"
rescue Exception
begin
raise ArgumentError
rescue ArgumentError
end
# should raise StandardError "aaa"
raise
end
end.should raise_error(StandardError, "aaa")
end
end
describe "Kernel#raise" do

View File

@ -10,9 +10,9 @@ end
describe "Kernel.select" do
it 'does not block when timeout is 0' do
IO.pipe do |read, write|
IO.select([read], [], [], 0).should == nil
select([read], [], [], 0).should == nil
write.write 'data'
IO.select([read], [], [], 0).should == [[read], [], []]
select([read], [], [], 0).should == [[read], [], []]
end
end
end

View File

@ -51,6 +51,20 @@ describe "Kernel#sleep" do
t.value.should == 5
end
platform_is_not :darwin do
it "sleeps with nanosecond precision" do
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
100.times do
sleep(0.0001)
end
end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
actual_duration = end_time - start_time
(actual_duration > 0.01).should == true # 100 * 0.0001 => 0.01
(actual_duration < 0.03).should == true
end
end
ruby_version_is ""..."3.3" do
it "raises a TypeError when passed nil" do
-> { sleep(nil) }.should raise_error(TypeError)

View File

@ -1,4 +1,7 @@
# -*- encoding: binary -*-
require_relative 'marshal_multibyte_data'
class UserDefined
class Nested
def ==(other)
@ -267,17 +270,6 @@ module MarshalSpec
end
end
module_eval(<<~ruby.dup.force_encoding(Encoding::UTF_8))
class MultibyteぁあぃいClass
end
module MultibyteけげこごModule
end
class MultibyteぁあぃいTime < Time
end
ruby
class ObjectWithFreezeRaisingException < Object
def freeze
raise

View File

@ -0,0 +1,12 @@
# -*- encoding: utf-8 -*-
module MarshalSpec
class MultibyteぁあぃいClass
end
module MultibyteけげこごModule
end
class MultibyteぁあぃいTime < Time
end
end

View File

@ -21,6 +21,17 @@ describe "Module#ancestors" do
ModuleSpecs::Parent.ancestors.should == ModuleSpecs::Parent.ancestors.uniq
end
it "returns a module that is included later into a nested module as well" do
m1 = Module.new
m2 = Module.new
m3 = Module.new do
include m2
end
m2.include m1 # should be after m3 includes m2
m3.ancestors.should == [m3, m2, m1]
end
describe "when called on a singleton class" do
it "includes the singleton classes of ancestors" do
parent = Class.new

View File

@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'fixtures/const_added'
describe "Module#const_added" do
ruby_version_is "3.2" do
@ -63,6 +64,27 @@ describe "Module#const_added" do
ScratchPad.recorded.should == [:SubModule]
end
it "is called when a new module is defined under a named module (assigned to a constant)" do
ScratchPad.record []
ModuleSpecs::ConstAddedSpecs::NamedModule = Module.new do
def self.const_added(name)
ScratchPad << name
end
module self::A
def self.const_added(name)
ScratchPad << name
end
module self::B
end
end
end
ScratchPad.recorded.should == [:A, :B]
end
it "is called when a new class is defined under self" do
ScratchPad.record []
@ -83,6 +105,27 @@ describe "Module#const_added" do
ScratchPad.recorded.should == [:SubClass]
end
it "is called when a new class is defined under a named module (assigned to a constant)" do
ScratchPad.record []
ModuleSpecs::ConstAddedSpecs::NamedModuleB = Module.new do
def self.const_added(name)
ScratchPad << name
end
class self::A
def self.const_added(name)
ScratchPad << name
end
class self::B
end
end
end
ScratchPad.recorded.should == [:A, :B]
end
it "is called when an autoload is defined" do
ScratchPad.record []

View File

@ -0,0 +1,4 @@
module ModuleSpecs
module ConstAddedSpecs
end
end

View File

@ -7,4 +7,7 @@ module ModuleSpecs
.name
end
end
module NameSpecs
end
end

View File

@ -581,6 +581,29 @@ describe "Module#include" do
c2.include(m)
c2.new.foo.should == [:c2, :m1]
end
it "update a module when a nested module is updated and includes a module on its own" do
m1 = Module.new
m2 = Module.new do
def m2; [:m2]; end
end
m3 = Module.new do
def m3; [:m3]; end
end
m4 = Module.new do
def m4; [:m4]; end
end
c = Class.new
c.include(m1)
m1.include(m2)
m2.include(m3)
m3.include(m4)
c.new.m2.should == [:m2]
c.new.m3.should == [:m3]
c.new.m4.should == [:m4]
end
end
describe "Module#include?" do

View File

@ -140,6 +140,47 @@ describe "Module#name" do
valid_names.should include(m::N.name) # You get one of the two, but you don't know which one.
end
ruby_version_is "3.2" do
it "is set in #const_added callback when a module defined in the top-level scope" do
ruby_exe(<<~RUBY, args: "2>&1").chomp.should == "TEST1\nTEST2"
class Module
def const_added(name)
puts const_get(name).name
end
end
# module with name
module TEST1
end
# anonymous module
TEST2 = Module.new
RUBY
end
it "is set in #const_added callback for a nested module when an outer module defined in the top-level scope" do
ScratchPad.record []
ModuleSpecs::NameSpecs::NamedModule = Module.new do
def self.const_added(name)
ScratchPad << const_get(name).name
end
module self::A
def self.const_added(name)
ScratchPad << const_get(name).name
end
module self::B
end
end
end
ScratchPad.recorded.should.one?(/#<Module.+>::A$/)
ScratchPad.recorded.should.one?(/#<Module.+>::A::B$/)
end
end
it "returns a frozen String" do
ModuleSpecs.name.should.frozen?
end

View File

@ -245,7 +245,7 @@ describe "Module#refine" do
ruby_version_is ""..."3.2" do
it "looks in the included modules for builtin methods" do
result = ruby_exe(<<-RUBY)
result = ruby_exe(<<-RUBY)
a = Module.new do
def /(other) quo(other) end
end

View File

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

View File

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

View File

@ -168,6 +168,31 @@ describe "ObjectSpace.define_finalizer" do
ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"]
end
it "defines same finalizer only once" do
code = <<~RUBY
obj = Object.new
p = proc { |id| print "ok" }
ObjectSpace.define_finalizer(obj, p.dup)
ObjectSpace.define_finalizer(obj, p.dup)
RUBY
ruby_exe(code).should == "ok"
end
it "returns the defined finalizer" do
obj = Object.new
p = proc { |id| }
p2 = p.dup
ret = ObjectSpace.define_finalizer(obj, p)
ret.should == [0, p]
ret[1].should.equal?(p)
ret = ObjectSpace.define_finalizer(obj, p2)
ret.should == [0, p]
ret[1].should.equal?(p)
end
ruby_version_is "3.1" do
describe "when $VERBOSE is not nil" do
it "warns if an exception is raised in finalizer" do

View File

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

View File

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

View File

@ -1,5 +1,33 @@
require_relative '../../spec_helper'
describe "ObjectSpace.undefine_finalizer" do
it "needs to be reviewed for spec completeness"
it "removes finalizers for an object" do
code = <<~RUBY
obj = Object.new
ObjectSpace.define_finalizer(obj, proc { |id| puts "hello" })
ObjectSpace.undefine_finalizer(obj)
RUBY
ruby_exe(code).should.empty?
end
it "should not remove finalizers for a frozen object" do
code = <<~RUBY
obj = Object.new
ObjectSpace.define_finalizer(obj, proc { |id| print "ok" })
obj.freeze
begin
ObjectSpace.undefine_finalizer(obj)
rescue
end
RUBY
ruby_exe(code).should == "ok"
end
it "should raise when removing finalizers for a frozen object" do
obj = Object.new
obj.freeze
-> { ObjectSpace.undefine_finalizer(obj) }.should raise_error(FrozenError)
end
end

View File

@ -159,15 +159,14 @@ describe "Proc#curry with arity argument" do
end
it "can be passed more than _arity_ arguments if created from a proc" do
-> { @proc_add.curry(3)[1,2,3,4].should == 6 }.should_not
raise_error(ArgumentError)
-> { @proc_add.curry(1)[1,2].curry(3)[3,4,5,6].should == 6 }.should_not
raise_error(ArgumentError)
@proc_add.curry(3)[1,2,3,4].should == 6
@proc_add.curry(3)[1,2].curry(3)[3,4,5,6].should == 6
end
it "raises an ArgumentError if passed more than _arity_ arguments when created from a lambda" do
-> { @lambda_add.curry(3)[1,2,3,4] }.should raise_error(ArgumentError)
-> { @lambda_add.curry(1)[1,2].curry(3)[3,4,5,6] }.should raise_error(ArgumentError)
-> { @lambda_add.curry(3)[1,2].curry(3)[3,4,5,6] }.should raise_error(ArgumentError)
end
it "returns Procs with arities of -1 regardless of the value of _arity_" do

View File

@ -2,69 +2,91 @@ require_relative '../../spec_helper'
describe "Process::Constants" do
platform_is :darwin, :netbsd, :freebsd do
it "has the correct constant values on BSD-like systems" do
Process::WNOHANG.should == 1
Process::WUNTRACED.should == 2
Process::PRIO_PROCESS.should == 0
Process::PRIO_PGRP.should == 1
Process::PRIO_USER.should == 2
Process::RLIM_INFINITY.should == 9223372036854775807
Process::RLIMIT_CPU.should == 0
Process::RLIMIT_FSIZE.should == 1
Process::RLIMIT_DATA.should == 2
Process::RLIMIT_STACK.should == 3
Process::RLIMIT_CORE.should == 4
Process::RLIMIT_RSS.should == 5
Process::RLIMIT_MEMLOCK.should == 6
Process::RLIMIT_NPROC.should == 7
Process::RLIMIT_NOFILE.should == 8
it "are all present on BSD-like systems" do
%i[
WNOHANG
WUNTRACED
PRIO_PROCESS
PRIO_PGRP
PRIO_USER
RLIM_INFINITY
RLIMIT_CPU
RLIMIT_FSIZE
RLIMIT_DATA
RLIMIT_STACK
RLIMIT_CORE
RLIMIT_RSS
RLIMIT_MEMLOCK
RLIMIT_NPROC
RLIMIT_NOFILE
].each do |const|
Process.const_defined?(const).should be_true
Process.const_get(const).should be_an_instance_of(Integer)
end
end
end
platform_is :darwin do
it "has the correct constant values on Darwin" do
Process::RLIM_SAVED_MAX.should == 9223372036854775807
Process::RLIM_SAVED_CUR.should == 9223372036854775807
Process::RLIMIT_AS.should == 5
it "are all present on Darwin" do
%i[
RLIM_SAVED_MAX
RLIM_SAVED_CUR
RLIMIT_AS
].each do |const|
Process.const_defined?(const).should be_true
Process.const_get(const).should be_an_instance_of(Integer)
end
end
end
platform_is :linux do
it "has the correct constant values on Linux" do
Process::WNOHANG.should == 1
Process::WUNTRACED.should == 2
Process::PRIO_PROCESS.should == 0
Process::PRIO_PGRP.should == 1
Process::PRIO_USER.should == 2
Process::RLIMIT_CPU.should == 0
Process::RLIMIT_FSIZE.should == 1
Process::RLIMIT_DATA.should == 2
Process::RLIMIT_STACK.should == 3
Process::RLIMIT_CORE.should == 4
Process::RLIMIT_RSS.should == 5
Process::RLIMIT_NPROC.should == 6
Process::RLIMIT_NOFILE.should == 7
Process::RLIMIT_MEMLOCK.should == 8
Process::RLIMIT_AS.should == 9
# These values appear to change according to the platform.
values = [4294967295, 9223372036854775807, 18446744073709551615]
values.include?(Process::RLIM_INFINITY).should be_true
values.include?(Process::RLIM_SAVED_MAX).should be_true
values.include?(Process::RLIM_SAVED_CUR).should be_true
it "are all present on Linux" do
%i[
WNOHANG
WUNTRACED
PRIO_PROCESS
PRIO_PGRP
PRIO_USER
RLIMIT_CPU
RLIMIT_FSIZE
RLIMIT_DATA
RLIMIT_STACK
RLIMIT_CORE
RLIMIT_RSS
RLIMIT_NPROC
RLIMIT_NOFILE
RLIMIT_MEMLOCK
RLIMIT_AS
RLIM_INFINITY
RLIM_SAVED_MAX
RLIM_SAVED_CUR
].each do |const|
Process.const_defined?(const).should be_true
Process.const_get(const).should be_an_instance_of(Integer)
end
end
end
platform_is :netbsd, :freebsd do
it "has the correct constant values on NetBSD and FreeBSD" do
Process::RLIMIT_SBSIZE.should == 9 # FIXME: what's it equal?
Process::RLIMIT_AS.should == 10
it "are all present on NetBSD and FreeBSD" do
%i[
RLIMIT_SBSIZE
RLIMIT_AS
].each do |const|
Process.const_defined?(const).should be_true
Process.const_get(const).should be_an_instance_of(Integer)
end
end
end
platform_is :freebsd do
it "has the correct constant values on FreeBSD" do
Process::RLIMIT_NPTS.should == 11
it "are all present on FreeBSD" do
%i[
RLIMIT_NPTS
].each do |const|
Process.const_defined?(const).should be_true
Process.const_get(const).should be_an_instance_of(Integer)
end
end
end

View File

@ -0,0 +1,6 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/freeze'
describe "Queue#freeze" do
it_behaves_like :queue_freeze, :freeze, -> { Queue.new }
end

View File

@ -460,6 +460,10 @@ describe :regexp_new_string, shared: true do
-> { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode list: /\\u{}/")))
end
it "raises a RegexpError if the \\u{} escape contains non hexadecimal digits" do
-> { Regexp.send(@method, "\\" + "u{abcX}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode list: /\\u{abcX}/")))
end
it "raises a RegexpError if more than six hexadecimal digits are given" do
-> { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode range: /\\u{0ffffff}/")))
end

View File

@ -2,8 +2,8 @@
describe :regexp_quote, shared: true do
it "escapes any characters with special meaning in a regular expression" do
Regexp.send(@method, '\*?{}.+^[]()- ').should == '\\\\\*\?\{\}\.\+\^\[\]\(\)\-\\ '
Regexp.send(@method, "\*?{}.+^[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\[\\]\\(\\)\\-\\ '
Regexp.send(@method, '\*?{}.+^$[]()- ').should == '\\\\\*\?\{\}\.\+\^\$\[\]\(\)\-\\ '
Regexp.send(@method, "\*?{}.+^$[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\$\\[\\]\\(\\)\\-\\ '
Regexp.send(@method, '\n\r\f\t').should == '\\\\n\\\\r\\\\f\\\\t'
Regexp.send(@method, "\n\r\f\t").should == '\\n\\r\\f\\t'
end

View File

@ -0,0 +1,6 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/freeze'
describe "SizedQueue#freeze" do
it_behaves_like :queue_freeze, :freeze, -> { SizedQueue.new(1) }
end

View File

@ -17,7 +17,7 @@ describe "String#byteslice with Range" do
it_behaves_like :string_slice_range, :byteslice
end
describe "String#byteslice on on non ASCII strings" do
describe "String#byteslice on non ASCII strings" do
it "returns byteslice of unicode strings" do
"\u3042".byteslice(1).should == "\x81".dup.force_encoding("UTF-8")
"\u3042".byteslice(1, 2).should == "\x81\x82".dup.force_encoding("UTF-8")

View File

@ -58,6 +58,79 @@ describe "String#bytesplice" do
-> { s.bytesplice(2, 1, "xxx") }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"")
end
end
ruby_version_is "3.3" do
it "raises IndexError when str_index is less than -bytesize" do
-> { "hello".bytesplice(2, 1, "HELLO", -6, 0) }.should raise_error(IndexError, "index -6 out of string")
end
it "raises IndexError when str_index is greater than bytesize" do
-> { "hello".bytesplice(2, 1, "HELLO", 6, 0) }.should raise_error(IndexError, "index 6 out of string")
end
it "raises IndexError for negative str length" do
-> { "abc".bytesplice(0, 1, "", 0, -2) }.should raise_error(IndexError, "negative length -2")
end
it "replaces with integer str indices" do
"hello".bytesplice(1, 2, "HELLO", -5, 0).should == "hlo"
"hello".bytesplice(1, 2, "HELLO", 0, 0).should == "hlo"
"hello".bytesplice(1, 2, "HELLO", 0, 1).should == "hHlo"
"hello".bytesplice(1, 2, "HELLO", 0, 5).should == "hHELLOlo"
"hello".bytesplice(1, 2, "HELLO", 0, 6).should == "hHELLOlo"
end
it "raises RangeError when str range left boundary is less than -bytesize" do
-> { "hello".bytesplice(0..1, "HELLO", -6...-6) }.should raise_error(RangeError, "-6...-6 out of range")
end
it "replaces with str ranges" do
"hello".bytesplice(1..2, "HELLO", -5...-5).should == "hlo"
"hello".bytesplice(1..2, "HELLO", 0...0).should == "hlo"
"hello".bytesplice(1..2, "HELLO", 0..0).should == "hHlo"
"hello".bytesplice(1..2, "HELLO", 0...1).should == "hHlo"
"hello".bytesplice(1..2, "HELLO", 0..1).should == "hHElo"
"hello".bytesplice(1..2, "HELLO", 0..-1).should == "hHELLOlo"
"hello".bytesplice(1..2, "HELLO", 0...5).should == "hHELLOlo"
"hello".bytesplice(1..2, "HELLO", 0...6).should == "hHELLOlo"
end
it "raises ArgumentError when integer str index is provided without str length argument" do
-> { "hello".bytesplice(0, 1, "xxx", 0) }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 2, 3, or 5)")
end
it "replaces on an empty string with str index/length" do
"".bytesplice(0, 0, "", 0, 0).should == ""
"".bytesplice(0, 0, "xxx", 0, 1).should == "x"
end
it "mutates self with substring and str index/length" do
s = "hello"
s.bytesplice(2, 1, "xxx", 1, 2).should.equal?(s)
s.should.eql?("hexxlo")
end
it "raises when string is frozen and str index/length" do
s = "hello".freeze
-> { s.bytesplice(2, 1, "xxx", 0, 1) }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"")
end
it "replaces on an empty string with str range" do
"".bytesplice(0..0, "", 0..0).should == ""
"".bytesplice(0..0, "xyz", 0..1).should == "xy"
end
it "mutates self with substring and str range" do
s = "hello"
s.bytesplice(2..2, "xyz", 1..2).should.equal?(s)
s.should.eql?("heyzlo")
end
it "raises when string is frozen and str range" do
s = "hello".freeze
-> { s.bytesplice(2..2, "yzx", 0..1) }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"")
end
end
end
describe "String#bytesplice with multibyte characters" do
@ -131,4 +204,95 @@ describe "String#bytesplice with multibyte characters" do
result.encoding.should == Encoding::UTF_8
end
end
ruby_version_is "3.3" do
it "raises IndexError when str_index is out of byte size boundary" do
-> { "こんにちは".bytesplice(3, 3, "こんにちは", -16, 0) }.should raise_error(IndexError, "index -16 out of string")
end
it "raises IndexError when str_index is not on a codepoint boundary" do
-> { "こんにちは".bytesplice(3, 3, "こんにちは", 1, 0) }.should raise_error(IndexError, "offset 1 does not land on character boundary")
end
it "raises IndexError when str_length is not matching the codepoint boundary" do
-> { "こんにちは".bytesplice(3, 3, "こんにちは", 0, 1) }.should raise_error(IndexError, "offset 1 does not land on character boundary")
-> { "こんにちは".bytesplice(3, 3, "こんにちは", 0, 2) }.should raise_error(IndexError, "offset 2 does not land on character boundary")
end
it "replaces with integer str indices" do
"こんにちは".bytesplice(3, 3, "こんにちは", -15, 0).should == "こにちは"
"こんにちは".bytesplice(3, 3, "こんにちは", 0, 0).should == "こにちは"
"こんにちは".bytesplice(3, 3, "こんにちは", 0, 3).should == "ここにちは"
"こんにちは".bytesplice(3, 3, "はは", 3, 3).should == "こはにちは"
"こんにちは".bytesplice(3, 3, "こんにちは", 15, 0).should == "こにちは"
end
it "replaces with str range" do
"こんにちは".bytesplice(0..2, "こんにちは", -15...-16).should == "んにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 0...0).should == "んにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 3..5).should == "んんにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 3...6).should == "んんにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 3..8).should == "んにんにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 0..-1).should == "こんにちはんにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 0...15).should == "こんにちはんにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 0...18).should == "こんにちはんにちは"
end
it "treats negative length for str range as 0" do
"こんにちは".bytesplice(0..2, "こんにちは", 0...-100).should == "んにちは"
"こんにちは".bytesplice(0..2, "こんにちは", 3...-100).should == "んにちは"
"こんにちは".bytesplice(0..2, "こんにちは", -15...-100).should == "んにちは"
end
it "raises when ranges not match codepoint boundaries in str" do
-> { "こんにちは".bytesplice(3...3, "", 0..0) }.should raise_error(IndexError, "offset 1 does not land on character boundary")
-> { "こんにちは".bytesplice(3...3, "", 0..1) }.should raise_error(IndexError, "offset 2 does not land on character boundary")
# Begin is incorrect
-> { "こんにちは".bytesplice(3...3, "こんにちは", -4..-1) }.should raise_error(IndexError, "offset 11 does not land on character boundary")
-> { "こんにちは".bytesplice(3...3, "こんにちは", -5..-1) }.should raise_error(IndexError, "offset 10 does not land on character boundary")
# End is incorrect
-> { "こんにちは".bytesplice(3...3, "こんにちは", -3..-2) }.should raise_error(IndexError, "offset 14 does not land on character boundary")
-> { "こんにちは".bytesplice(3...3, "こんにちは", -3..-3) }.should raise_error(IndexError, "offset 13 does not land on character boundary")
end
it "deals with a different encoded argument with str index/length" do
s = "こんにちは"
s.encoding.should == Encoding::UTF_8
sub = "goodbye"
sub.force_encoding(Encoding::US_ASCII)
result = s.bytesplice(3, 3, sub, 0, 3)
result.should == "こgooにちは"
result.encoding.should == Encoding::UTF_8
s = "hello"
s.force_encoding(Encoding::US_ASCII)
sub = "こんにちは"
sub.encoding.should == Encoding::UTF_8
result = s.bytesplice(1, 2, sub, 3, 3)
result.should == "hんlo"
result.encoding.should == Encoding::UTF_8
end
it "deals with a different encoded argument with str range" do
s = "こんにちは"
s.encoding.should == Encoding::UTF_8
sub = "goodbye"
sub.force_encoding(Encoding::US_ASCII)
result = s.bytesplice(3..5, sub, 0..2)
result.should == "こgooにちは"
result.encoding.should == Encoding::UTF_8
s = "hello"
s.force_encoding(Encoding::US_ASCII)
sub = "こんにちは"
sub.encoding.should == Encoding::UTF_8
result = s.bytesplice(1..2, sub, 3..5)
result.should == "hんlo"
result.encoding.should == Encoding::UTF_8
end
end
end

View File

@ -37,6 +37,17 @@ describe "Thread#[]" do
t2["value"].should == 2
end
it "converts a key that is neither String nor Symbol with #to_str" do
key = mock('value')
key.should_receive(:to_str).and_return('value')
th = Thread.new do
Thread.current[:value] = 1
end.join
th[key].should == 1
end
it "raises exceptions on the wrong type of keys" do
-> { Thread.current[nil] }.should raise_error(TypeError)
-> { Thread.current[5] }.should raise_error(TypeError)

View File

@ -12,10 +12,33 @@ describe "Thread#[]=" do
th.freeze
-> {
th[:foo] = "bar"
}.should raise_error(FrozenError, /frozen/)
}.should raise_error(FrozenError, "can't modify frozen thread locals")
end.join
end
it "accepts Strings and Symbols" do
t1 = Thread.new do
Thread.current[:value] = 1
end.join
t2 = Thread.new do
Thread.current["value"] = 2
end.join
t1[:value].should == 1
t2[:value].should == 2
end
it "converts a key that is neither String nor Symbol with #to_str" do
key = mock('value')
key.should_receive(:to_str).and_return('value')
th = Thread.new do
Thread.current[key] = 1
end.join
th[:value].should == 1
end
it "raises exceptions on the wrong type of keys" do
-> { Thread.current[nil] = true }.should raise_error(TypeError)
-> { Thread.current[5] = true }.should raise_error(TypeError)

View File

@ -1,5 +1,16 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Thread#group" do
it "needs to be reviewed for spec completeness"
it "returns the default thread group for the main thread" do
Thread.main.group.should == ThreadGroup::Default
end
it "returns the thread group explicitly set for this thread" do
thread = Thread.new { nil }
thread_group = ThreadGroup.new
thread_group.add(thread)
thread.group.should == thread_group
ensure
thread.join if thread
end
end

View File

@ -16,6 +16,13 @@ describe "Thread#key?" do
@th.key?(:stanley.to_s).should == false
end
it "converts a key that is neither String nor Symbol with #to_str" do
key = mock('key')
key.should_receive(:to_str).and_return('oliver')
@th.key?(key).should == true
end
it "raises exceptions on the wrong type of keys" do
-> { Thread.current.key? nil }.should raise_error(TypeError)
-> { Thread.current.key? 5 }.should raise_error(TypeError)

View File

@ -485,6 +485,8 @@ describe "Time.new with a timezone argument" do
Time.new("2020-12-25 00:56:17 +0900").should == t
Time.new("2020-12-25 00:57:47 +090130").should == t
Time.new("2020-12-25T00:56:17+09:00").should == t
Time.new("2020-12-25T00:56:17.123456+09:00").should == Time.utc(2020, 12, 24, 15, 56, 17, 123456)
end
it "accepts precision keyword argument and truncates specified digits of sub-second part" do
@ -511,6 +513,16 @@ describe "Time.new with a timezone argument" do
Time.new("2021-12-25 00:00:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 -0100"
end
it "returns Time of Jan 1 for string with just year" do
Time.new("2021").should == Time.new(2021, 1, 1)
Time.new("2021").zone.should == Time.new(2021, 1, 1).zone
Time.new("2021").utc_offset.should == Time.new(2021, 1, 1).utc_offset
end
it "returns Time of Jan 1 for string with just year in timezone specified with in keyword argument" do
Time.new("2021", in: "+17:00").to_s.should == "2021-01-01 00:00:00 +1700"
end
it "converts precision keyword argument into Integer if is not nil" do
obj = Object.new
def obj.to_int; 3; end
@ -539,101 +551,109 @@ describe "Time.new with a timezone argument" do
it "raises ArgumentError if part of time string is missing" do
-> {
Time.new("2020-12-25 00:56 +09:00")
}.should raise_error(ArgumentError, "missing sec part: 00:56 ")
}.should raise_error(ArgumentError, /missing sec part: 00:56 |can't parse:/)
-> {
Time.new("2020-12-25 00 +09:00")
}.should raise_error(ArgumentError, "missing min part: 00 ")
}.should raise_error(ArgumentError, /missing min part: 00 |can't parse:/)
end
ruby_version_is "3.2.3" do
it "raises ArgumentError if the time part is missing" do
-> {
Time.new("2020-12-25")
}.should raise_error(ArgumentError, /no time information|can't parse:/)
end
end
it "raises ArgumentError if subsecond is missing after dot" do
-> {
Time.new("2020-12-25 00:56:17. +0900")
}.should raise_error(ArgumentError, "subsecond expected after dot: 00:56:17. ")
}.should raise_error(ArgumentError, /subsecond expected after dot: 00:56:17. |can't parse:/)
end
it "raises ArgumentError if String argument is not in the supported format" do
-> {
Time.new("021-12-25 00:00:00.123456 +09:00")
}.should raise_error(ArgumentError, "year must be 4 or more digits: 021")
}.should raise_error(ArgumentError, /year must be 4 or more digits: 021|can't parse:/)
-> {
Time.new("2020-012-25 00:56:17 +0900")
}.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z/)
}.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z|can't parse:/)
-> {
Time.new("2020-2-25 00:56:17 +0900")
}.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z/)
}.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z|can't parse:/)
-> {
Time.new("2020-12-215 00:56:17 +0900")
}.should raise_error(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z/)
}.should raise_error(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z|can't parse:/)
-> {
Time.new("2020-12-25 000:56:17 +0900")
}.should raise_error(ArgumentError, "two digits hour is expected: 000:56:17 ")
}.should raise_error(ArgumentError, /two digits hour is expected: 000:56:17 |can't parse:/)
-> {
Time.new("2020-12-25 0:56:17 +0900")
}.should raise_error(ArgumentError, "two digits hour is expected: 0:56:17 +0")
}.should raise_error(ArgumentError, /two digits hour is expected: 0:56:17 \+0|can't parse:/)
-> {
Time.new("2020-12-25 00:516:17 +0900")
}.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z/)
}.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z|can't parse:/)
-> {
Time.new("2020-12-25 00:6:17 +0900")
}.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z/)
}.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z|can't parse:/)
-> {
Time.new("2020-12-25 00:56:137 +0900")
}.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z/)
}.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z|can't parse:/)
-> {
Time.new("2020-12-25 00:56:7 +0900")
}.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z/)
}.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z|can't parse:/)
-> {
Time.new("2020-12-25 00:56. +0900")
}.should raise_error(ArgumentError, "fraction min is not supported: 00:56.")
}.should raise_error(ArgumentError, /fraction min is not supported: 00:56\.|can't parse:/)
-> {
Time.new("2020-12-25 00. +0900")
}.should raise_error(ArgumentError, "fraction hour is not supported: 00.")
}.should raise_error(ArgumentError, /fraction hour is not supported: 00\.|can't parse:/)
end
it "raises ArgumentError if date/time parts values are not valid" do
-> {
Time.new("2020-13-25 00:56:17 +09:00")
}.should raise_error(ArgumentError, "mon out of range")
}.should raise_error(ArgumentError, /(mon|argument) out of range/)
-> {
Time.new("2020-12-32 00:56:17 +09:00")
}.should raise_error(ArgumentError, "mday out of range")
}.should raise_error(ArgumentError, /(mday|argument) out of range/)
-> {
Time.new("2020-12-25 25:56:17 +09:00")
}.should raise_error(ArgumentError, "hour out of range")
}.should raise_error(ArgumentError, /(hour|argument) out of range/)
-> {
Time.new("2020-12-25 00:61:17 +09:00")
}.should raise_error(ArgumentError, "min out of range")
}.should raise_error(ArgumentError, /(min|argument) out of range/)
-> {
Time.new("2020-12-25 00:56:61 +09:00")
}.should raise_error(ArgumentError, "sec out of range")
}.should raise_error(ArgumentError, /(sec|argument) out of range/)
-> {
Time.new("2020-12-25 00:56:17 +23:59:60")
}.should raise_error(ArgumentError, /utc_offset/)
}.should raise_error(ArgumentError, /utc_offset|argument out of range/)
-> {
Time.new("2020-12-25 00:56:17 +24:00")
}.should raise_error(ArgumentError, /utc_offset/)
}.should raise_error(ArgumentError, /(utc_offset|argument) out of range/)
-> {
Time.new("2020-12-25 00:56:17 +23:61")
}.should raise_error(ArgumentError, /utc_offset/)
}.should raise_error(ArgumentError, /utc_offset|can't parse:/)
ruby_bug '#20797', ''...'3.4' do
-> {
@ -647,6 +667,18 @@ describe "Time.new with a timezone argument" do
Time.new("2021-11-31 00:00:60 +09:00".encode("utf-32le"))
}.should raise_error(ArgumentError, "time string should have ASCII compatible encoding")
end
it "raises ArgumentError if string doesn't start with year" do
-> {
Time.new("a\nb")
}.should raise_error(ArgumentError, "can't parse: \"a\\nb\"")
end
it "raises ArgumentError if string has extra characters after offset" do
-> {
Time.new("2021-11-31 00:00:59 +09:00 abc")
}.should raise_error(ArgumentError, /can't parse.+ abc/)
end
end
end
end

View File

@ -121,7 +121,7 @@ describe "Warning.warn" do
end
end
ruby_bug '#19530', ''...'3.4' do
ruby_bug '#20573', ''...'3.4' do
it "isn't called by Kernel.warn when category is :deprecated but Warning[:deprecated] is false" do
warn_deprecated = Warning[:deprecated]
begin

View File

@ -10,7 +10,7 @@
# variety in class and module configurations, including hierarchy,
# containment, inclusion, singletons and toplevel.
#
# Constants are numbered for for uniqueness. The CS_ prefix is uniformly used
# Constants are numbered for uniqueness. The CS_ prefix is uniformly used
# and is to minimize clashes with other toplevel constants (see e.g. ModuleA
# which is included in Object). Constant values are symbols. A numbered suffix
# is used to distinguish constants with the same name defined in different

View File

@ -43,17 +43,17 @@ module Private
end
end
class E
include D
end
class E
include D
end
class G
def foo
"foo"
end
end
class G
def foo
"foo"
end
end
class H < A
private :foo
end
class H < A
private :foo
end
end

View File

@ -43,9 +43,9 @@ module LangSendSpecs
attr_writer :foo
private :foo=
def call_self_foo_equals(value)
self.foo = value
end
def call_self_foo_equals(value)
self.foo = value
end
def call_self_foo_equals_masgn(value)
a, self.foo = 1, value

View File

@ -294,14 +294,14 @@ describe "Operators" do
-> { eval("1...2...3") }.should raise_error(SyntaxError)
end
it ".. ... have higher precedence than ? :" do
# Use variables to avoid warnings
from = 1
to = 2
# These are flip-flop, not Range instances
(from..to ? 3 : 4).should == 3
(from...to ? 3 : 4).should == 3
end
it ".. ... have higher precedence than ? :" do
# Use variables to avoid warnings
from = 1
to = 2
# These are flip-flop, not Range instances
(from..to ? 3 : 4).should == 3
(from...to ? 3 : 4).should == 3
end
it "? : is right-associative" do
(true ? 2 : 3 ? 4 : 5).should == 2

View File

@ -243,6 +243,16 @@ describe "Predefined global $stdout" do
end
describe "Predefined global $!" do
it "is Fiber-local" do
Fiber.new do
raise "hi"
rescue
Fiber.yield
end.resume
$!.should == nil
end
# See http://jira.codehaus.org/browse/JRUBY-5550
it "remains nil after a failed core class \"checked\" coercion against a class that defines method_missing" do
$!.should == nil

View File

@ -62,7 +62,7 @@ describe "Literal Regexps" do
end
end
it "supports non-paired delimiters delimiters with %r" do
it "supports non-paired delimiters with %r" do
LanguageSpecs.non_paired_delimiters.each do |c|
eval("%r#{c} foo #{c}").should == / foo /
end

View File

@ -70,7 +70,7 @@ describe "The super keyword" do
SuperSpecs::S4::B.new.foo([],"test").should == ["B#foo(a,test)", "A#foo"]
end
it "raises an error error when super method does not exist" do
it "raises an error when super method does not exist" do
sup = Class.new
sub_normal = Class.new(sup) do
def foo

View File

@ -2,20 +2,20 @@ require_relative '../../spec_helper'
require 'bigdecimal'
describe "BigDecimal#fix" do
before :each do
@zero = BigDecimal("0")
@mixed = BigDecimal("1.23456789")
@pos_int = BigDecimal("2E5555")
@neg_int = BigDecimal("-2E5555")
@pos_frac = BigDecimal("2E-9999")
@neg_frac = BigDecimal("-2E-9999")
before :each do
@zero = BigDecimal("0")
@mixed = BigDecimal("1.23456789")
@pos_int = BigDecimal("2E5555")
@neg_int = BigDecimal("-2E5555")
@pos_frac = BigDecimal("2E-9999")
@neg_frac = BigDecimal("-2E-9999")
@infinity = BigDecimal("Infinity")
@infinity_neg = BigDecimal("-Infinity")
@nan = BigDecimal("NaN")
@zero_pos = BigDecimal("+0")
@zero_neg = BigDecimal("-0")
end
@infinity = BigDecimal("Infinity")
@infinity_neg = BigDecimal("-Infinity")
@nan = BigDecimal("NaN")
@zero_pos = BigDecimal("+0")
@zero_neg = BigDecimal("-0")
end
it "returns a BigDecimal" do
BigDecimal("2E100000000").fix.kind_of?(BigDecimal).should == true

View File

@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative 'shared/month'
require 'date'
describe "Date#mon" do
it "needs to be reviewed for spec completeness"
it_behaves_like :date_month, :mon
end

View File

@ -1,9 +1,7 @@
require_relative '../../spec_helper'
require_relative 'shared/month'
require 'date'
describe "Date#month" do
it "returns the month" do
m = Date.new(2000, 7, 1).month
m.should == 7
end
it_behaves_like :date_month, :month
end

View File

@ -0,0 +1,6 @@
describe :date_month, shared: true do
it "returns the month" do
m = Date.new(2000, 7, 1).send(@method)
m.should == 7
end
end

View File

@ -130,7 +130,7 @@ END
<b><%#= item %></b>
<%# end %>
END
ERBSpecs.new_erb(input).result.should == "\n<b></b>\n\n"
ERBSpecs.new_erb(input).result.should == "\n<b></b>\n\n"
ERBSpecs.new_erb(input, trim_mode: '<>').result.should == "<b></b>\n"
end

View File

@ -13,19 +13,19 @@ describe "Logger#new" do
rm_r @file_path
end
it "creates a new logger object" do
l = Logger.new(STDERR)
-> { l.add(Logger::WARN, "Foo") }.should output_to_fd(/Foo/, STDERR)
end
it "creates a new logger object" do
l = Logger.new(STDERR)
-> { l.add(Logger::WARN, "Foo") }.should output_to_fd(/Foo/, STDERR)
end
it "receives a logging device as first argument" do
l = Logger.new(@log_file)
l.add(Logger::WARN, "Test message")
it "receives a logging device as first argument" do
l = Logger.new(@log_file)
l.add(Logger::WARN, "Test message")
@log_file.rewind
LoggerSpecs.strip_date(@log_file.readline).should == "WARN -- : Test message\n"
l.close
end
@log_file.rewind
LoggerSpecs.strip_date(@log_file.readline).should == "WARN -- : Test message\n"
l.close
end
it "receives a frequency rotation as second argument" do
-> { Logger.new(@log_file, "daily") }.should_not raise_error

View File

@ -21,6 +21,10 @@ describe 'Pathname.glob' do
Pathname.glob(@dir + 'lib/*.js').should == []
end
it 'returns [] when the pathname does not exist' do
Pathname.glob('i_dont_exist/lib/*.js').should == []
end
it 'returns matching file paths' do
Pathname.glob(@dir + 'lib/*i*.rb').sort.should == [Pathname.new(@file_1), Pathname.new(@file_2)].sort
end
@ -67,6 +71,10 @@ describe 'Pathname#glob' do
Pathname.new(@dir).glob('lib/*.js').should == []
end
it 'returns [] when the pathname does not exist' do
Pathname.new('./i_dont_exist').glob('lib/*.js').should == []
end
it 'returns matching file paths' do
Pathname.new(@dir).glob('lib/*i*.rb').sort.should == [Pathname.new(@file_1), Pathname.new(@file_2)].sort
end

View File

@ -9,6 +9,13 @@ describe 'RbConfig::CONFIG' do
end
end
it 'has MAJOR, MINOR, TEENY, and PATCHLEVEL matching RUBY_VERSION and RUBY_PATCHLEVEL' do
major, minor, teeny = RUBY_VERSION.split('.')
RbConfig::CONFIG.values_at("MAJOR", "MINOR", "TEENY", "PATCHLEVEL").should == [
major, minor, teeny, RUBY_PATCHLEVEL.to_s
]
end
# These directories have no meanings before the installation.
guard -> { RbConfig::TOPDIR } do
it "['rubylibdir'] returns the directory containing Ruby standard libraries" do

View File

@ -10,4 +10,9 @@ describe "Set#hash" do
Set[].hash.should_not == Set[1, 2, 3].hash
Set[1, 2, 3].hash.should_not == Set[:a, "b", ?c].hash
end
# see https://github.com/jruby/jruby/issues/8393
it "is equal to nil.hash for an uninitialized Set" do
Set.allocate.hash.should == nil.hash
end
end

View File

@ -16,4 +16,16 @@ describe "Set#merge" do
-> { Set[1, 2].merge(1) }.should raise_error(ArgumentError)
-> { Set[1, 2].merge(Object.new) }.should raise_error(ArgumentError)
end
ruby_version_is ""..."3.3" do
it "accepts only a single argument" do
-> { Set[].merge([], []) }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 1)")
end
end
ruby_version_is "3.3" do
it "accepts multiple arguments" do
Set[:a, :b].merge(Set[:b, :c], [:d]).should == Set[:a, :b, :c, :d]
end
end
end

View File

@ -335,7 +335,7 @@ describe "Addrinfo#initialize" do
@sockaddr = ['AF_INET6', 80, 'hostname', '127.0.0.1']
end
it "raises SocketError when using any Socket constant except except AF_INET(6)/PF_INET(6)" do
it "raises SocketError when using any Socket constant except AF_INET(6)/PF_INET(6)" do
Socket.constants.grep(/(^AF_|^PF_)(?!INET)/).each do |constant|
value = Socket.const_get(constant)
-> {

View File

@ -16,27 +16,27 @@ describe "BasicSocket#send" do
@socket.close
end
it "sends a message to another socket and returns the number of bytes sent" do
data = +""
t = Thread.new do
client = @server.accept
loop do
got = client.recv(5)
break if got.nil? || got.empty?
data << got
end
client.close
end
Thread.pass while t.status and t.status != "sleep"
t.status.should_not be_nil
it "sends a message to another socket and returns the number of bytes sent" do
data = +""
t = Thread.new do
client = @server.accept
loop do
got = client.recv(5)
break if got.nil? || got.empty?
data << got
end
client.close
end
Thread.pass while t.status and t.status != "sleep"
t.status.should_not be_nil
@socket.send('hello', 0).should == 5
@socket.shutdown(1) # indicate, that we are done sending
@socket.recv(10)
@socket.send('hello', 0).should == 5
@socket.shutdown(1) # indicate, that we are done sending
@socket.recv(10)
t.join
data.should == 'hello'
end
t.join
data.should == 'hello'
end
platform_is_not :solaris, :windows do
it "accepts flags to specify unusual sending behaviour" do

View File

@ -4,12 +4,12 @@ class StringSubclass < String; end
module StringIOSpecs
def self.build
str = <<-EOS
str = <<-EOS
each
peach
pear
plum
EOS
EOS
StringIO.new(str)
end
end

View File

@ -0,0 +1,237 @@
require 'stringio'
require_relative '../../spec_helper'
# Should be synced with specs for IO#set_encoding_by_bom
describe "StringIO#set_encoding_by_bom" do
it "returns nil if not readable" do
io = StringIO.new("".b, "wb")
io.set_encoding_by_bom.should be_nil
io.external_encoding.should == Encoding::ASCII_8BIT
end
it "returns the result encoding if found BOM UTF-8 sequence" do
io = StringIO.new("\u{FEFF}".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_8
io.external_encoding.should == Encoding::UTF_8
io.read.b.should == "".b
io = StringIO.new("\u{FEFF}abc".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_8
io.external_encoding.should == Encoding::UTF_8
io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_16LE sequence" do
io = StringIO.new("\xFF\xFE".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_16LE
io.external_encoding.should == Encoding::UTF_16LE
io.read.b.should == "".b
io = StringIO.new("\xFF\xFEabc".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_16LE
io.external_encoding.should == Encoding::UTF_16LE
io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_16BE sequence" do
io = StringIO.new("\xFE\xFF".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_16BE
io.external_encoding.should == Encoding::UTF_16BE
io.read.b.should == "".b
io = StringIO.new("\xFE\xFFabc".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_16BE
io.external_encoding.should == Encoding::UTF_16BE
io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_32LE sequence" do
io = StringIO.new("\xFF\xFE\x00\x00".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_32LE
io.external_encoding.should == Encoding::UTF_32LE
io.read.b.should == "".b
io = StringIO.new("\xFF\xFE\x00\x00abc".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_32LE
io.external_encoding.should == Encoding::UTF_32LE
io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_32BE sequence" do
io = StringIO.new("\x00\x00\xFE\xFF".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_32BE
io.external_encoding.should == Encoding::UTF_32BE
io.read.b.should == "".b
io = StringIO.new("\x00\x00\xFE\xFFabc".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_32BE
io.external_encoding.should == Encoding::UTF_32BE
io.read.b.should == "abc".b
end
it "returns nil if io is empty" do
io = StringIO.new("".b, "rb")
io.set_encoding_by_bom.should be_nil
io.external_encoding.should == Encoding::ASCII_8BIT
end
it "returns nil if UTF-8 BOM sequence is incomplete" do
io = StringIO.new("\xEF".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xEF".b
io = StringIO.new("\xEFa".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xEFa".b
io = StringIO.new("\xEF\xBB".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xEF\xBB".b
io = StringIO.new("\xEF\xBBa".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xEF\xBBa".b
end
it "returns nil if UTF-16BE BOM sequence is incomplete" do
io = StringIO.new("\xFE".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xFE".b
io = StringIO.new("\xFEa".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xFEa".b
end
it "returns nil if UTF-16LE/UTF-32LE BOM sequence is incomplete" do
io = StringIO.new("\xFF".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xFF".b
io = StringIO.new("\xFFa".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\xFFa".b
end
it "returns UTF-16LE if UTF-32LE BOM sequence is incomplete" do
io = StringIO.new("\xFF\xFE".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_16LE
io.external_encoding.should == Encoding::UTF_16LE
io.read.b.should == "".b
io = StringIO.new("\xFF\xFE\x00".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_16LE
io.external_encoding.should == Encoding::UTF_16LE
io.read.b.should == "\x00".b
io = StringIO.new("\xFF\xFE\x00a".b, "rb")
io.set_encoding_by_bom.should == Encoding::UTF_16LE
io.external_encoding.should == Encoding::UTF_16LE
io.read.b.should == "\x00a".b
end
it "returns nil if UTF-32BE BOM sequence is incomplete" do
io = StringIO.new("\x00".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\x00".b
io = StringIO.new("\x00a".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\x00a".b
io = StringIO.new("\x00\x00".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\x00\x00".b
io = StringIO.new("\x00\x00a".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\x00\x00a".b
io = StringIO.new("\x00\x00\xFE".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\x00\x00\xFE".b
io = StringIO.new("\x00\x00\xFEa".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read.b.should == "\x00\x00\xFEa".b
end
it "returns nil if found BOM sequence not provided" do
io = StringIO.new("abc".b, "rb")
io.set_encoding_by_bom.should == nil
io.external_encoding.should == Encoding::ASCII_8BIT
io.read(3).should == "abc".b
end
it "does not raise exception if io not in binary mode" do
io = StringIO.new("", 'r')
io.set_encoding_by_bom.should == nil
end
it "does not raise exception if encoding already set" do
io = StringIO.new("".b, "rb")
io.set_encoding("utf-8")
io.set_encoding_by_bom.should == nil
end
it "does not raise exception if encoding conversion is already set" do
io = StringIO.new("".b, "rb")
io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE)
io.set_encoding_by_bom.should == nil
end
it "raises FrozenError when io is frozen" do
io = StringIO.new()
io.freeze
-> { io.set_encoding_by_bom }.should raise_error(FrozenError)
end
it "does not raise FrozenError when initial string is frozen" do
io = StringIO.new("".freeze)
io.set_encoding_by_bom.should == nil
end
end

View File

@ -10,6 +10,6 @@ describe :stringio_sysread_length, shared: true do
it "raises an EOFError when passed length > 0 and no data remains" do
@io.read.should == "example"
-> { @io.sysread(1) }.should raise_error(EOFError)
-> { @io.send(@method, 1) }.should raise_error(EOFError)
end
end

View File

@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require "stringio"
require_relative 'shared/read'
require_relative 'shared/sysread'
describe "StringIO#sysread when passed length, buffer" do
it_behaves_like :stringio_read, :sysread
@ -32,6 +33,10 @@ describe "StringIO#sysread when passed nil" do
end
end
describe "StringIO#sysread when passed length" do
it_behaves_like :stringio_sysread_length, :sysread
end
describe "StringIO#sysread when passed [length]" do
before :each do
@io = StringIO.new("example")

View File

@ -1,33 +1,33 @@
describe :time_rfc2822, shared: true do
it "parses RFC-822 strings" do
t1 = (Time.utc(1976, 8, 26, 14, 30) + 4 * 3600)
t2 = Time.rfc2822("26 Aug 76 14:30 EDT")
t2 = Time.send(@method, "26 Aug 76 14:30 EDT")
t1.should == t2
t3 = Time.utc(1976, 8, 27, 9, 32) + 7 * 3600
t4 = Time.rfc2822("27 Aug 76 09:32 PDT")
t4 = Time.send(@method, "27 Aug 76 09:32 PDT")
t3.should == t4
end
it "parses RFC-2822 strings" do
t1 = Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600
t2 = Time.rfc2822("Fri, 21 Nov 1997 09:55:06 -0600")
t2 = Time.send(@method, "Fri, 21 Nov 1997 09:55:06 -0600")
t1.should == t2
t3 = Time.utc(2003, 7, 1, 10, 52, 37) - 2 * 3600
t4 = Time.rfc2822("Tue, 1 Jul 2003 10:52:37 +0200")
t4 = Time.send(@method, "Tue, 1 Jul 2003 10:52:37 +0200")
t3.should == t4
t5 = Time.utc(1997, 11, 21, 10, 1, 10) + 6 * 3600
t6 = Time.rfc2822("Fri, 21 Nov 1997 10:01:10 -0600")
t6 = Time.send(@method, "Fri, 21 Nov 1997 10:01:10 -0600")
t5.should == t6
t7 = Time.utc(1997, 11, 21, 11, 0, 0) + 6 * 3600
t8 = Time.rfc2822("Fri, 21 Nov 1997 11:00:00 -0600")
t8 = Time.send(@method, "Fri, 21 Nov 1997 11:00:00 -0600")
t7.should == t8
t9 = Time.utc(1997, 11, 24, 14, 22, 1) + 8 * 3600
t10 = Time.rfc2822("Mon, 24 Nov 1997 14:22:01 -0800")
t10 = Time.send(@method, "Mon, 24 Nov 1997 14:22:01 -0800")
t9.should == t10
begin
@ -36,11 +36,11 @@ describe :time_rfc2822, shared: true do
# ignore
else
t11 = Time.utc(1969, 2, 13, 23, 32, 54) + 3 * 3600 + 30 * 60
t12 = Time.rfc2822("Thu, 13 Feb 1969 23:32:54 -0330")
t12 = Time.send(@method, "Thu, 13 Feb 1969 23:32:54 -0330")
t11.should == t12
t13 = Time.utc(1969, 2, 13, 23, 32, 0) + 3 * 3600 + 30 * 60
t14 = Time.rfc2822(" Thu,
t14 = Time.send(@method, " Thu,
13
Feb
1969
@ -50,16 +50,16 @@ describe :time_rfc2822, shared: true do
end
t15 = Time.utc(1997, 11, 21, 9, 55, 6)
t16 = Time.rfc2822("21 Nov 97 09:55:06 GMT")
t16 = Time.send(@method, "21 Nov 97 09:55:06 GMT")
t15.should == t16
t17 = Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600
t18 = Time.rfc2822("Fri, 21 Nov 1997 09 : 55 : 06 -0600")
t18 = Time.send(@method, "Fri, 21 Nov 1997 09 : 55 : 06 -0600")
t17.should == t18
-> {
# inner comment is not supported.
Time.rfc2822("Fri, 21 Nov 1997 09(comment): 55 : 06 -0600")
Time.send(@method, "Fri, 21 Nov 1997 09(comment): 55 : 06 -0600")
}.should raise_error(ArgumentError)
end
end

View File

@ -2,23 +2,23 @@ describe :time_library_xmlschema, shared: true do
it "parses ISO-8601 strings" do
t = Time.utc(1985, 4, 12, 23, 20, 50, 520000)
s = "1985-04-12T23:20:50.52Z"
t.should == Time.xmlschema(s)
#s.should == t.xmlschema(2)
t.should == Time.send(@method, s)
#s.should == t.send(@method, 2)
t = Time.utc(1996, 12, 20, 0, 39, 57)
s = "1996-12-19T16:39:57-08:00"
t.should == Time.xmlschema(s)
t.should == Time.send(@method, s)
# There is no way to generate time string with arbitrary timezone.
s = "1996-12-20T00:39:57Z"
t.should == Time.xmlschema(s)
#assert_equal(s, t.xmlschema)
t.should == Time.send(@method, s)
#assert_equal(s, t.send(@method))
t = Time.utc(1990, 12, 31, 23, 59, 60)
s = "1990-12-31T23:59:60Z"
t.should == Time.xmlschema(s)
t.should == Time.send(@method, s)
# leap second is representable only if timezone file has it.
s = "1990-12-31T15:59:60-08:00"
t.should == Time.xmlschema(s)
t.should == Time.send(@method, s)
begin
Time.at(-1)
@ -27,27 +27,27 @@ describe :time_library_xmlschema, shared: true do
else
t = Time.utc(1937, 1, 1, 11, 40, 27, 870000)
s = "1937-01-01T12:00:27.87+00:20"
t.should == Time.xmlschema(s)
t.should == Time.send(@method, s)
end
# more
# (Time.utc(1999, 5, 31, 13, 20, 0) + 5 * 3600).should == Time.xmlschema("1999-05-31T13:20:00-05:00")
# (Time.local(2000, 1, 20, 12, 0, 0)).should == Time.xmlschema("2000-01-20T12:00:00")
# (Time.utc(2000, 1, 20, 12, 0, 0)).should == Time.xmlschema("2000-01-20T12:00:00Z")
# (Time.utc(2000, 1, 20, 12, 0, 0) - 12 * 3600).should == Time.xmlschema("2000-01-20T12:00:00+12:00")
# (Time.utc(2000, 1, 20, 12, 0, 0) + 13 * 3600).should == Time.xmlschema("2000-01-20T12:00:00-13:00")
# (Time.utc(2000, 3, 4, 23, 0, 0) - 3 * 3600).should == Time.xmlschema("2000-03-04T23:00:00+03:00")
# (Time.utc(2000, 3, 4, 20, 0, 0)).should == Time.xmlschema("2000-03-04T20:00:00Z")
# (Time.local(2000, 1, 15, 0, 0, 0)).should == Time.xmlschema("2000-01-15T00:00:00")
# (Time.local(2000, 2, 15, 0, 0, 0)).should == Time.xmlschema("2000-02-15T00:00:00")
# (Time.local(2000, 1, 15, 12, 0, 0)).should == Time.xmlschema("2000-01-15T12:00:00")
# (Time.utc(2000, 1, 16, 12, 0, 0)).should == Time.xmlschema("2000-01-16T12:00:00Z")
# (Time.local(2000, 1, 1, 12, 0, 0)).should == Time.xmlschema("2000-01-01T12:00:00")
# (Time.utc(1999, 12, 31, 23, 0, 0)).should == Time.xmlschema("1999-12-31T23:00:00Z")
# (Time.local(2000, 1, 16, 12, 0, 0)).should == Time.xmlschema("2000-01-16T12:00:00")
# (Time.local(2000, 1, 16, 0, 0, 0)).should == Time.xmlschema("2000-01-16T00:00:00")
# (Time.utc(2000, 1, 12, 12, 13, 14)).should == Time.xmlschema("2000-01-12T12:13:14Z")
# (Time.utc(2001, 4, 17, 19, 23, 17, 300000)).should == Time.xmlschema("2001-04-17T19:23:17.3Z")
# (Time.utc(1999, 5, 31, 13, 20, 0) + 5 * 3600).should == Time.send(@method, "1999-05-31T13:20:00-05:00")
# (Time.local(2000, 1, 20, 12, 0, 0)).should == Time.send(@method, "2000-01-20T12:00:00")
# (Time.utc(2000, 1, 20, 12, 0, 0)).should == Time.send(@method, "2000-01-20T12:00:00Z")
# (Time.utc(2000, 1, 20, 12, 0, 0) - 12 * 3600).should == Time.send(@method, "2000-01-20T12:00:00+12:00")
# (Time.utc(2000, 1, 20, 12, 0, 0) + 13 * 3600).should == Time.send(@method, "2000-01-20T12:00:00-13:00")
# (Time.utc(2000, 3, 4, 23, 0, 0) - 3 * 3600).should == Time.send(@method, "2000-03-04T23:00:00+03:00")
# (Time.utc(2000, 3, 4, 20, 0, 0)).should == Time.send(@method, "2000-03-04T20:00:00Z")
# (Time.local(2000, 1, 15, 0, 0, 0)).should == Time.send(@method, "2000-01-15T00:00:00")
# (Time.local(2000, 2, 15, 0, 0, 0)).should == Time.send(@method, "2000-02-15T00:00:00")
# (Time.local(2000, 1, 15, 12, 0, 0)).should == Time.send(@method, "2000-01-15T12:00:00")
# (Time.utc(2000, 1, 16, 12, 0, 0)).should == Time.send(@method, "2000-01-16T12:00:00Z")
# (Time.local(2000, 1, 1, 12, 0, 0)).should == Time.send(@method, "2000-01-01T12:00:00")
# (Time.utc(1999, 12, 31, 23, 0, 0)).should == Time.send(@method, "1999-12-31T23:00:00Z")
# (Time.local(2000, 1, 16, 12, 0, 0)).should == Time.send(@method, "2000-01-16T12:00:00")
# (Time.local(2000, 1, 16, 0, 0, 0)).should == Time.send(@method, "2000-01-16T00:00:00")
# (Time.utc(2000, 1, 12, 12, 13, 14)).should == Time.send(@method, "2000-01-12T12:13:14Z")
# (Time.utc(2001, 4, 17, 19, 23, 17, 300000)).should == Time.send(@method, "2001-04-17T19:23:17.3Z")
end
end

View File

@ -7,16 +7,12 @@
extern "C" {
#endif
VALUE kernel_spec_call_proc(VALUE arg_array) {
static VALUE kernel_spec_call_proc(VALUE arg_array) {
VALUE arg = rb_ary_pop(arg_array);
VALUE proc = rb_ary_pop(arg_array);
return rb_funcall(proc, rb_intern("call"), 1, arg);
}
VALUE kernel_spec_call_proc_raise(VALUE arg_array, VALUE raised_exc) {
return kernel_spec_call_proc(arg_array);
}
static VALUE kernel_spec_rb_block_given_p(VALUE self) {
return rb_block_given_p() ? Qtrue : Qfalse;
}
@ -134,7 +130,16 @@ VALUE kernel_spec_rb_throw_obj(VALUE self, VALUE obj, VALUE result) {
return ID2SYM(rb_intern("rb_throw_failed"));
}
VALUE kernel_spec_call_proc_with_raised_exc(VALUE arg_array, VALUE raised_exc) {
VALUE kernel_spec_rb_errinfo(VALUE self) {
return rb_errinfo();
}
VALUE kernel_spec_rb_set_errinfo(VALUE self, VALUE exc) {
rb_set_errinfo(exc);
return Qnil;
}
static VALUE kernel_spec_call_proc_with_raised_exc(VALUE arg_array, VALUE raised_exc) {
VALUE argv[2];
int argc;
@ -181,7 +186,7 @@ VALUE kernel_spec_rb_rescue2(int argc, VALUE *args, VALUE self) {
rb_ary_push(raise_array, args[3]);
return rb_rescue2(kernel_spec_call_proc, main_array,
kernel_spec_call_proc_raise, raise_array, args[4], args[5], (VALUE)0);
kernel_spec_call_proc_with_raised_exc, raise_array, args[4], args[5], (VALUE)0);
}
static VALUE kernel_spec_rb_protect_yield(VALUE self, VALUE obj, VALUE ary) {
@ -195,7 +200,7 @@ static VALUE kernel_spec_rb_protect_yield(VALUE self, VALUE obj, VALUE ary) {
return res;
}
static VALUE kernel_spec_rb_protect_errinfo(VALUE self, VALUE obj, VALUE ary) {
static VALUE kernel_spec_rb_protect_ignore_status(VALUE self, VALUE obj, VALUE ary) {
int status = 0;
VALUE res = rb_protect(rb_yield, obj, &status);
rb_ary_store(ary, 0, INT2NUM(23));
@ -382,10 +387,13 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_raise", kernel_spec_rb_raise, 1);
rb_define_method(cls, "rb_throw", kernel_spec_rb_throw, 1);
rb_define_method(cls, "rb_throw_obj", kernel_spec_rb_throw_obj, 2);
rb_define_method(cls, "rb_errinfo", kernel_spec_rb_errinfo, 0);
rb_define_method(cls, "rb_set_errinfo", kernel_spec_rb_set_errinfo, 1);
rb_define_method(cls, "rb_rescue", kernel_spec_rb_rescue, 4);
rb_define_method(cls, "rb_rescue", kernel_spec_rb_rescue, 4);
rb_define_method(cls, "rb_rescue2", kernel_spec_rb_rescue2, -1);
rb_define_method(cls, "rb_protect_yield", kernel_spec_rb_protect_yield, 2);
rb_define_method(cls, "rb_protect_errinfo", kernel_spec_rb_protect_errinfo, 2);
rb_define_method(cls, "rb_protect_ignore_status", kernel_spec_rb_protect_ignore_status, 2);
rb_define_method(cls, "rb_protect_null_status", kernel_spec_rb_protect_null_status, 1);
rb_define_method(cls, "rb_eval_string_protect", kernel_spec_rb_eval_string_protect, 2);
rb_define_method(cls, "rb_catch", kernel_spec_rb_catch, 2);

View File

@ -29,15 +29,34 @@ VALUE mutex_spec_rb_mutex_sleep(VALUE self, VALUE mutex, VALUE timeout) {
return rb_mutex_sleep(mutex, timeout);
}
VALUE mutex_spec_rb_mutex_callback(VALUE arg) {
return rb_funcall(arg, rb_intern("call"), 0);
}
VALUE mutex_spec_rb_mutex_naughty_callback(VALUE arg) {
int *result = (int *) arg;
return (VALUE) result;
}
VALUE mutex_spec_rb_mutex_callback_basic(VALUE arg) {
return arg;
}
VALUE mutex_spec_rb_mutex_synchronize(VALUE self, VALUE mutex, VALUE value) {
return rb_mutex_synchronize(mutex, mutex_spec_rb_mutex_callback, value);
}
VALUE mutex_spec_rb_mutex_synchronize_with_naughty_callback(VALUE self, VALUE mutex) {
// a naughty callback accepts or returns not a Ruby object but arbitrary value
int arg = 42;
VALUE result = rb_mutex_synchronize(mutex, mutex_spec_rb_mutex_naughty_callback, (VALUE) &arg);
return INT2NUM(*((int *) result));
}
VALUE mutex_spec_rb_mutex_synchronize_with_native_callback(VALUE self, VALUE mutex, VALUE value) {
return rb_mutex_synchronize(mutex, mutex_spec_rb_mutex_callback_basic, value);
}
void Init_mutex_spec(void) {
VALUE cls = rb_define_class("CApiMutexSpecs", rb_cObject);
rb_define_method(cls, "rb_mutex_new", mutex_spec_rb_mutex_new, 0);
@ -47,6 +66,8 @@ void Init_mutex_spec(void) {
rb_define_method(cls, "rb_mutex_unlock", mutex_spec_rb_mutex_unlock, 1);
rb_define_method(cls, "rb_mutex_sleep", mutex_spec_rb_mutex_sleep, 2);
rb_define_method(cls, "rb_mutex_synchronize", mutex_spec_rb_mutex_synchronize, 2);
rb_define_method(cls, "rb_mutex_synchronize_with_naughty_callback", mutex_spec_rb_mutex_synchronize_with_naughty_callback, 1);
rb_define_method(cls, "rb_mutex_synchronize_with_native_callback", mutex_spec_rb_mutex_synchronize_with_native_callback, 2);
}
#ifdef __cplusplus

View File

@ -117,6 +117,10 @@ VALUE string_spec_rb_str_cmp(VALUE self, VALUE str1, VALUE str2) {
return INT2NUM(rb_str_cmp(str1, str2));
}
VALUE string_spec_rb_str_strlen(VALUE self, VALUE str) {
return LONG2NUM(rb_str_strlen(str));
}
VALUE string_spec_rb_str_conv_enc(VALUE self, VALUE str, VALUE from, VALUE to) {
rb_encoding* from_enc;
rb_encoding* to_enc;
@ -600,6 +604,7 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_str_cat_cstr", string_spec_rb_str_cat_cstr, 2);
rb_define_method(cls, "rb_str_cat_cstr_constant", string_spec_rb_str_cat_cstr_constant, 1);
rb_define_method(cls, "rb_str_cmp", string_spec_rb_str_cmp, 2);
rb_define_method(cls, "rb_str_strlen", string_spec_rb_str_strlen, 1);
rb_define_method(cls, "rb_str_conv_enc", string_spec_rb_str_conv_enc, 3);
rb_define_method(cls, "rb_str_conv_enc_opts", string_spec_rb_str_conv_enc_opts, 5);
rb_define_method(cls, "rb_str_drop_bytes", string_spec_rb_str_drop_bytes, 2);

View File

@ -3,11 +3,19 @@ require_relative 'fixtures/kernel'
kernel_path = load_extension("kernel")
class CApiKernelSpecs::Exc < StandardError
end
exception_class = CApiKernelSpecs::Exc
describe "C-API Kernel function" do
before :each do
@s = CApiKernelSpecs.new
end
after :each do
@s.rb_errinfo.should == nil
end
describe "rb_block_given_p" do
it "returns false if no block is passed" do
@s.should_not.rb_block_given_p
@ -78,6 +86,22 @@ describe "C-API Kernel function" do
-> { @s.rb_raise(h) }.should raise_error(TypeError)
h[:stage].should == :before
end
it "re-raises a rescued exception" do
-> do
begin
raise StandardError, "aaa"
rescue Exception
begin
@s.rb_raise({})
rescue TypeError
end
# should raise StandardError "aaa"
raise
end
end.should raise_error(StandardError, "aaa")
end
end
describe "rb_throw" do
@ -295,7 +319,7 @@ describe "C-API Kernel function" do
it "will allow cleanup code to run after a raise" do
proof = [] # Hold proof of work performed after the yield.
-> do
@s.rb_protect_yield(77, proof) { |x| raise NameError}
@s.rb_protect_yield(77, proof) { |x| raise NameError }
end.should raise_error(NameError)
proof[0].should == 23
end
@ -303,7 +327,7 @@ describe "C-API Kernel function" do
it "will return nil if an error was raised" do
proof = [] # Hold proof of work performed after the yield.
-> do
@s.rb_protect_yield(77, proof) { |x| raise NameError}
@s.rb_protect_yield(77, proof) { |x| raise NameError }
end.should raise_error(NameError)
proof[0].should == 23
proof[1].should == nil
@ -311,14 +335,21 @@ describe "C-API Kernel function" do
it "accepts NULL as status and returns nil if it failed" do
@s.rb_protect_null_status(42) { |x| x + 1 }.should == 43
@s.rb_protect_null_status(42) { |x| raise }.should == nil
@s.rb_protect_null_status(42) { |x| raise NameError }.should == nil
@s.rb_errinfo().should.is_a? NameError
ensure
@s.rb_set_errinfo(nil)
end
it "populates errinfo with the captured exception" do
it "populates rb_errinfo() with the captured exception" do
proof = []
@s.rb_protect_errinfo(77, proof) { |x| raise NameError }.class.should == NameError
@s.rb_protect_ignore_status(77, proof) { |x| raise NameError }
@s.rb_errinfo().should.is_a? NameError
# Note: on CRuby $! is the NameError here, but not clear if that is desirable or bug
proof[0].should == 23
proof[1].should == nil
ensure
@s.rb_set_errinfo(nil)
end
end
@ -382,9 +413,21 @@ describe "C-API Kernel function" do
-> { @s.rb_rescue(@std_error_proc, nil, @std_error_proc, nil) }.should raise_error(StandardError)
end
it "makes $! available only during the 'rescue function' execution" do
@s.rb_rescue(@std_error_proc, nil, -> *_ { $! }, nil).class.should == StandardError
it "sets $! and rb_errinfo() during the 'rescue function' execution" do
@s.rb_rescue(-> *_ { raise exception_class, '' }, nil, -> _, exc {
exc.should.is_a?(exception_class)
$!.should.equal?(exc)
@s.rb_errinfo.should.equal?(exc)
}, nil)
@s.rb_rescue(-> _ { @s.rb_raise({}) }, nil, -> _, exc {
exc.should.is_a?(TypeError)
$!.should.equal?(exc)
@s.rb_errinfo.should.equal?(exc)
}, nil)
$!.should == nil
@s.rb_errinfo.should == nil
end
it "returns the break value if the passed function yields to a block with a break" do
@ -402,7 +445,7 @@ describe "C-API Kernel function" do
describe "rb_rescue2" do
it "only rescues if one of the passed exceptions is raised" do
proc = -> x { x }
proc = -> x, _exc { x }
arg_error_proc = -> *_ { raise ArgumentError, '' }
run_error_proc = -> *_ { raise RuntimeError, '' }
type_error_proc = -> *_ { raise Exception, 'custom error' }
@ -418,6 +461,23 @@ describe "C-API Kernel function" do
@s.rb_rescue2(-> *_ { raise RuntimeError, "foo" }, :no_exc, -> x { x }, :exc, Object.new, 42)
}.should raise_error(TypeError, /class or module required/)
end
it "sets $! and rb_errinfo() during the 'rescue function' execution" do
@s.rb_rescue2(-> *_ { raise exception_class, '' }, :no_exc, -> _, exc {
exc.should.is_a?(exception_class)
$!.should.equal?(exc)
@s.rb_errinfo.should.equal?(exc)
}, :exc, exception_class, ScriptError)
@s.rb_rescue2(-> *_ { @s.rb_raise({}) }, :no_exc, -> _, exc {
exc.should.is_a?(TypeError)
$!.should.equal?(exc)
@s.rb_errinfo.should.equal?(exc)
}, :exc, TypeError, ArgumentError)
$!.should == nil
@s.rb_errinfo.should == nil
end
end
describe "rb_catch" do
@ -486,12 +546,33 @@ describe "C-API Kernel function" do
it "executes passed 'ensure function' when an exception is raised" do
foo = nil
raise_proc = -> { raise '' }
raise_proc = -> _ { raise exception_class }
ensure_proc = -> x { foo = x }
@s.rb_ensure(raise_proc, nil, ensure_proc, :foo) rescue nil
-> {
@s.rb_ensure(raise_proc, nil, ensure_proc, :foo)
}.should raise_error(exception_class)
foo.should == :foo
end
it "sets $! and rb_errinfo() during the 'ensure function' execution" do
-> {
@s.rb_ensure(-> _ { raise exception_class }, nil, -> _ {
$!.should.is_a?(exception_class)
@s.rb_errinfo.should.is_a?(exception_class)
}, nil)
}.should raise_error(exception_class)
-> {
@s.rb_ensure(-> _ { @s.rb_raise({}) }, nil, -> _ {
$!.should.is_a?(TypeError)
@s.rb_errinfo.should.is_a?(TypeError)
}, nil)
}.should raise_error(TypeError)
$!.should == nil
@s.rb_errinfo.should == nil
end
it "raises the same exception raised inside passed function" do
raise_proc = -> *_ { raise RuntimeError, 'foo' }
proc = -> *_ { }

View File

@ -85,5 +85,18 @@ describe "C-API Mutex functions" do
callback = -> { @m.locked?.should be_true }
@s.rb_mutex_synchronize(@m, callback)
end
it "returns a value returned from a callback" do
callback = -> { :foo }
@s.rb_mutex_synchronize(@m, callback).should == :foo
end
it "calls a C-function that accepts and returns non-VALUE values" do
@s.rb_mutex_synchronize_with_naughty_callback(@m).should == 42
end
it "calls a native function" do
@s.rb_mutex_synchronize_with_native_callback(@m, 42).should == 42
end
end
end

View File

@ -449,6 +449,20 @@ describe "C-API String function" do
end
end
describe "rb_str_strlen" do
it 'returns 0 as the length of an empty string' do
@s.rb_str_strlen('').should == 0
end
it 'returns the number of characters in a string' do
@s.rb_str_strlen('hello').should == 5
end
it 'returns the number of characters in a string with multi-byte characters' do
@s.rb_str_strlen('こんにちは').should == 5
end
end
describe "rb_str_split" do
it "splits strings over a splitter" do
@s.rb_str_split("Hello,Goodbye").should == ["Hello", "Goodbye"]
@ -888,16 +902,20 @@ describe "C-API String function" do
end
it "returns the original String if a transcoding error occurs" do
a = [0xEE].pack('C').force_encoding("utf-8")
@s.rb_str_conv_enc(a, Encoding::UTF_8, Encoding::EUC_JP).should equal(a)
a = [0xEE].pack('C').force_encoding(Encoding::UTF_8)
@s.rb_str_conv_enc(a, Encoding::UTF_8, Encoding::EUC_JP).should.equal?(a)
a.encoding.should == Encoding::UTF_8
a = "\x80".b
@s.rb_str_conv_enc(a, Encoding::BINARY, Encoding::UTF_8).should.equal?(a)
a.encoding.should == Encoding::BINARY
end
it "returns a transcoded String" do
a = "\xE3\x81\x82\xE3\x82\x8C".dup.force_encoding("utf-8")
a = "\xE3\x81\x82\xE3\x82\x8C".dup.force_encoding(Encoding::UTF_8)
result = @s.rb_str_conv_enc(a, Encoding::UTF_8, Encoding::EUC_JP)
x = [0xA4, 0xA2, 0xA4, 0xEC].pack('C4').force_encoding('utf-8')
result.should == x.force_encoding("euc-jp")
result.encoding.should equal(Encoding::EUC_JP)
result.should == [0xA4, 0xA2, 0xA4, 0xEC].pack('C4').force_encoding(Encoding::EUC_JP)
result.encoding.should == Encoding::EUC_JP
end
describe "when the String encoding is equal to the destination encoding" do

View File

@ -0,0 +1,18 @@
describe :queue_freeze, shared: true do
ruby_version_is ""..."3.3" do
it "can be frozen" do
queue = @object.call
queue.freeze
queue.should.frozen?
end
end
ruby_version_is "3.3" do
it "raises an exception when freezing" do
queue = @object.call
-> {
queue.freeze
}.should raise_error(TypeError, "cannot freeze #{queue}")
end
end
end