summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/ruby/command_line/frozen_strings_spec.rb9
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb29
-rw-r--r--spec/ruby/core/dir/children_spec.rb13
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb13
-rw-r--r--spec/ruby/core/dir/each_spec.rb11
-rw-r--r--spec/ruby/core/exception/fixtures/syntax_error.rb3
-rw-r--r--spec/ruby/core/exception/syntax_error_spec.rb27
-rw-r--r--spec/ruby/core/hash/compare_by_identity_spec.rb4
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb4
-rw-r--r--spec/ruby/core/marshal/shared/load.rb2
-rw-r--r--spec/ruby/language/assignments_spec.rb379
-rw-r--r--spec/ruby/language/case_spec.rb13
-rw-r--r--spec/ruby/language/ensure_spec.rb2
-rw-r--r--spec/ruby/language/if_spec.rb9
-rw-r--r--spec/ruby/language/string_spec.rb13
-rw-r--r--spec/ruby/library/io-wait/wait_spec.rb37
-rw-r--r--spec/ruby/library/net-http/httpresponse/inspect_spec.rb2
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_body_spec.rb2
-rw-r--r--spec/ruby/library/net-http/httpresponse/reading_body_spec.rb2
-rw-r--r--spec/ruby/library/net-http/httpresponse/shared/body.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb32
-rw-r--r--spec/ruby/library/socket/basicsocket/read_spec.rb47
-rw-r--r--spec/ruby/library/stringio/fcntl_spec.rb2
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb2
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb2
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb20
-rw-r--r--spec/ruby/optional/capi/ext/gc_spec.c54
-rw-r--r--spec/ruby/optional/capi/gc_spec.rb31
28 files changed, 719 insertions, 47 deletions
diff --git a/spec/ruby/command_line/frozen_strings_spec.rb b/spec/ruby/command_line/frozen_strings_spec.rb
index 24b979b68b..334b98273b 100644
--- a/spec/ruby/command_line/frozen_strings_spec.rb
+++ b/spec/ruby/command_line/frozen_strings_spec.rb
@@ -28,6 +28,15 @@ describe "The --disable-frozen-string-literal flag causes string literals to" do
end
describe "With neither --enable-frozen-string-literal nor --disable-frozen-string-literal flag set" do
+ before do
+ # disable --enable-frozen-string-literal and --disable-frozen-string-literal passed in $RUBYOPT
+ @rubyopt = ENV["RUBYOPT"]
+ ENV["RUBYOPT"] = ""
+ end
+
+ after do
+ ENV["RUBYOPT"] = @rubyopt
+ end
it "produce a different object each time" do
ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb")).chomp.should == "false"
diff --git a/spec/ruby/core/class/subclasses_spec.rb b/spec/ruby/core/class/subclasses_spec.rb
index a16b934d4f..50eb5358d9 100644
--- a/spec/ruby/core/class/subclasses_spec.rb
+++ b/spec/ruby/core/class/subclasses_spec.rb
@@ -7,7 +7,7 @@ ruby_version_is '3.1' do
assert_subclasses(ModuleSpecs::Parent, [ModuleSpecs::Child, ModuleSpecs::Child2])
end
- it "does not return included modules" do
+ it "does not return included modules from the parent" do
parent = Class.new
child = Class.new(parent)
mod = Module.new
@@ -16,6 +16,33 @@ ruby_version_is '3.1' do
assert_subclasses(parent, [child])
end
+ it "does not return included modules from the child" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.include(mod)
+
+ assert_subclasses(parent, [child])
+ end
+
+ it "does not return prepended modules from the parent" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.prepend(mod)
+
+ assert_subclasses(parent, [child])
+ end
+
+ it "does not return prepended modules from the child" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ child.prepend(mod)
+
+ assert_subclasses(parent, [child])
+ end
+
it "does not return singleton classes" do
a = Class.new
diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb
index 92c593e5ba..0ad3df4669 100644
--- a/spec/ruby/core/dir/children_spec.rb
+++ b/spec/ruby/core/dir/children_spec.rb
@@ -131,4 +131,17 @@ describe "Dir#children" do
children = @dir.children.sort
children.first.encoding.should equal(Encoding::EUC_KR)
end
+
+ it "returns the same result when called repeatedly" do
+ @dir = Dir.open DirSpecs.mock_dir
+
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
end
diff --git a/spec/ruby/core/dir/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb
index 520186e79e..7194273b95 100644
--- a/spec/ruby/core/dir/each_child_spec.rb
+++ b/spec/ruby/core/dir/each_child_spec.rb
@@ -86,6 +86,19 @@ describe "Dir#each_child" do
@dir.each_child { |f| f }.should == @dir
end
+ it "returns the same result when called repeatedly" do
+ @dir = Dir.open DirSpecs.mock_dir
+
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
+
describe "when no block is given" do
it "returns an Enumerator" do
@dir = Dir.new(DirSpecs.mock_dir)
diff --git a/spec/ruby/core/dir/each_spec.rb b/spec/ruby/core/dir/each_spec.rb
index 8c69a7212b..7674663d82 100644
--- a/spec/ruby/core/dir/each_spec.rb
+++ b/spec/ruby/core/dir/each_spec.rb
@@ -35,6 +35,17 @@ describe "Dir#each" do
ls.should include(@dir.read)
end
+ it "returns the same result when called repeatedly" do
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
+
describe "when no block is given" do
it "returns an Enumerator" do
@dir.each.should be_an_instance_of(Enumerator)
diff --git a/spec/ruby/core/exception/fixtures/syntax_error.rb b/spec/ruby/core/exception/fixtures/syntax_error.rb
new file mode 100644
index 0000000000..ccec62f7a1
--- /dev/null
+++ b/spec/ruby/core/exception/fixtures/syntax_error.rb
@@ -0,0 +1,3 @@
+# rubocop:disable Lint/Syntax
+1+1=2
+# rubocop:enable Lint/Syntax
diff --git a/spec/ruby/core/exception/syntax_error_spec.rb b/spec/ruby/core/exception/syntax_error_spec.rb
new file mode 100644
index 0000000000..6cc8522de3
--- /dev/null
+++ b/spec/ruby/core/exception/syntax_error_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.2" do
+ describe "SyntaxError#path" do
+ it "returns the file path provided to eval" do
+ filename = "speccing.rb"
+
+ -> {
+ eval("if true", TOPLEVEL_BINDING, filename)
+ }.should raise_error(SyntaxError) { |e|
+ e.path.should == filename
+ }
+ end
+
+ it "returns the file path that raised an exception" do
+ expected_path = fixture(__FILE__, "syntax_error.rb")
+
+ -> {
+ require_relative "fixtures/syntax_error"
+ }.should raise_error(SyntaxError) { |e| e.path.should == expected_path }
+ end
+
+ it "returns nil when constructed directly" do
+ SyntaxError.new.path.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/hash/compare_by_identity_spec.rb b/spec/ruby/core/hash/compare_by_identity_spec.rb
index 3804f04bf6..2975526a97 100644
--- a/spec/ruby/core/hash/compare_by_identity_spec.rb
+++ b/spec/ruby/core/hash/compare_by_identity_spec.rb
@@ -110,6 +110,10 @@ describe "Hash#compare_by_identity" do
@idh.keys.first.should equal foo
end
+ # Check `#[]=` call with a String literal.
+ # Don't use `#+` because with `#+` it's no longer a String literal.
+ #
+ # See https://bugs.ruby-lang.org/issues/12855
it "gives different identity for string literals" do
eval <<~RUBY
# frozen_string_literal: false
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb
index 5d82f57e44..454bc4a58e 100644
--- a/spec/ruby/core/kernel/eval_spec.rb
+++ b/spec/ruby/core/kernel/eval_spec.rb
@@ -135,7 +135,7 @@ describe "Kernel#eval" do
it "includes file and line information in syntax error" do
expected = 'speccing.rb'
-> {
- eval('if true',TOPLEVEL_BINDING, expected)
+ eval('if true', TOPLEVEL_BINDING, expected)
}.should raise_error(SyntaxError) { |e|
e.message.should =~ /#{expected}:1:.+/
}
@@ -144,7 +144,7 @@ describe "Kernel#eval" do
it "evaluates string with given filename and negative linenumber" do
expected_file = 'speccing.rb'
-> {
- eval('if true',TOPLEVEL_BINDING, expected_file, -100)
+ eval('if true', TOPLEVEL_BINDING, expected_file, -100)
}.should raise_error(SyntaxError) { |e|
e.message.should =~ /#{expected_file}:-100:.+/
}
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index 1c8fa4c38c..f599042529 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -647,7 +647,7 @@ describe :marshal_load, shared: true do
end
it "sets binmode if it is loading through StringIO stream" do
- io = StringIO.new(+"\004\b:\vsymbol")
+ io = StringIO.new("\004\b:\vsymbol")
def io.binmode; raise "binmode"; end
-> { Marshal.load(io) }.should raise_error(RuntimeError, "binmode")
end
diff --git a/spec/ruby/language/assignments_spec.rb b/spec/ruby/language/assignments_spec.rb
index 005c1f0dc3..2773508d8d 100644
--- a/spec/ruby/language/assignments_spec.rb
+++ b/spec/ruby/language/assignments_spec.rb
@@ -1,7 +1,61 @@
require_relative '../spec_helper'
# Should be synchronized with spec/ruby/language/optional_assignments_spec.rb
+# Some specs for assignments are located in language/variables_spec.rb
describe 'Assignments' do
+ describe 'using =' do
+ describe 'evaluation order' do
+ it 'evaluates expressions left to right when assignment with an accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :receiver; object).a = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:receiver, :rhs]
+ end
+
+ it 'evaluates expressions left to right when assignment with a #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ (ScratchPad << :receiver; object)[(ScratchPad << :argument; :a)] = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:receiver, :argument, :rhs]
+ end
+
+ # similar tests for evaluation order are located in language/constants_spec.rb
+ ruby_version_is ''...'3.2' do
+ it 'evaluates expressions right to left when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:rhs, :module]
+ end
+ end
+
+ ruby_version_is '3.2' do
+ it 'evaluates expressions left to right when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:module, :rhs]
+ end
+ end
+
+ it 'raises TypeError after evaluation of right-hand-side when compounded constant module is not a module' do
+ ScratchPad.record []
+
+ -> {
+ (:not_a_module)::A = (ScratchPad << :rhs; :value)
+ }.should raise_error(TypeError)
+
+ ScratchPad.recorded.should == [:rhs]
+ end
+ end
+ end
+
describe 'using +=' do
describe 'using an accessor' do
before do
@@ -148,3 +202,328 @@ describe 'Assignments' do
end
end
end
+
+# generic cases
+describe 'Multiple assignments' do
+ it 'assigns multiple targets when assignment with an accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+ end
+
+ object.a, object.b = :a, :b
+
+ object.a.should == :a
+ object.b.should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a nested accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+ end
+
+ (object.a, object.b), c = [:a, :b], nil
+
+ object.a.should == :a
+ object.b.should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a #[]=' do
+ object = Object.new
+ class << object
+ def []=(k, v) (@h ||= {})[k] = v; end
+ def [](k) (@h ||= {})[k]; end
+ end
+
+ object[:a], object[:b] = :a, :b
+
+ object[:a].should == :a
+ object[:b].should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a nested #[]=' do
+ object = Object.new
+ class << object
+ def []=(k, v) (@h ||= {})[k] = v; end
+ def [](k) (@h ||= {})[k]; end
+ end
+
+ (object[:a], object[:b]), c = [:v1, :v2], nil
+
+ object[:a].should == :v1
+ object[:b].should == :v2
+ end
+
+ it 'assigns multiple targets when assignment with compounded constant' do
+ m = Module.new
+
+ m::A, m::B = :a, :b
+
+ m::A.should == :a
+ m::B.should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a nested compounded constant' do
+ m = Module.new
+
+ (m::A, m::B), c = [:a, :b], nil
+
+ m::A.should == :a
+ m::B.should == :b
+ end
+end
+
+describe 'Multiple assignments' do
+ describe 'evaluation order' do
+ ruby_version_is ''...'3.1' do
+ it 'evaluates expressions right to left when assignment with an accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; object).a, (ScratchPad << :b; object).a = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:c, :d, :a, :b]
+ end
+
+ it 'evaluates expressions right to left when assignment with a nested accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ ((ScratchPad << :a; object).a, foo), bar = [(ScratchPad << :b; :b)]
+ ScratchPad.recorded.should == [:b, :a]
+ end
+ end
+
+ ruby_version_is '3.1' do
+ it 'evaluates expressions left to right when assignment with an accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; object).a, (ScratchPad << :b; object).a = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:a, :b, :c, :d]
+ end
+
+ it 'evaluates expressions left to right when assignment with a nested accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ ((ScratchPad << :a; object).a, foo), bar = [(ScratchPad << :b; :b)]
+ ScratchPad.recorded.should == [:a, :b]
+ end
+
+ it 'evaluates expressions left to right when assignment with a deeply nested accessor' do
+ o = Object.new
+ def o.a=(value) end
+ def o.b=(value) end
+ def o.c=(value) end
+ def o.d=(value) end
+ def o.e=(value) end
+ def o.f=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; o).a,
+ ((ScratchPad << :b; o).b,
+ ((ScratchPad << :c; o).c, (ScratchPad << :d; o).d),
+ (ScratchPad << :e; o).e),
+ (ScratchPad << :f; o).f = (ScratchPad << :value; :value)
+
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
+ end
+ end
+
+ ruby_version_is ''...'3.1' do
+ it 'evaluates expressions right to left when assignment with a #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; object)[(ScratchPad << :b; :b)], (ScratchPad << :c; object)[(ScratchPad << :d; :d)] = (ScratchPad << :e; :e), (ScratchPad << :f; :f)
+ ScratchPad.recorded.should == [:e, :f, :a, :b, :c, :d]
+ end
+
+ it 'evaluates expressions right to left when assignment with a nested #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ ((ScratchPad << :a; object)[(ScratchPad << :b; :b)], foo), bar = [(ScratchPad << :c; :c)]
+ ScratchPad.recorded.should == [:c, :a, :b]
+ end
+ end
+
+ ruby_version_is '3.1' do
+ it 'evaluates expressions left to right when assignment with a #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; object)[(ScratchPad << :b; :b)], (ScratchPad << :c; object)[(ScratchPad << :d; :d)] = (ScratchPad << :e; :e), (ScratchPad << :f; :f)
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f]
+ end
+
+ it 'evaluates expressions left to right when assignment with a nested #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ ((ScratchPad << :a; object)[(ScratchPad << :b; :b)], foo), bar = [(ScratchPad << :c; :c)]
+ ScratchPad.recorded.should == [:a, :b, :c]
+ end
+
+ it 'evaluates expressions left to right when assignment with a deeply nested #[]=' do
+ o = Object.new
+ def o.[]=(_, _) end
+ ScratchPad.record []
+
+ (ScratchPad << :ra; o)[(ScratchPad << :aa; :aa)],
+ ((ScratchPad << :rb; o)[(ScratchPad << :ab; :ab)],
+ ((ScratchPad << :rc; o)[(ScratchPad << :ac; :ac)], (ScratchPad << :rd; o)[(ScratchPad << :ad; :ad)]),
+ (ScratchPad << :re; o)[(ScratchPad << :ae; :ae)]),
+ (ScratchPad << :rf; o)[(ScratchPad << :af; :af)] = (ScratchPad << :value; :value)
+
+ ScratchPad.recorded.should == [:ra, :aa, :rb, :ab, :rc, :ac, :rd, :ad, :re, :ae, :rf, :af, :value]
+ end
+ end
+
+ ruby_version_is ''...'3.2' do
+ it 'evaluates expressions right to left when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:c, :d, :a, :b]
+ end
+ end
+
+ ruby_version_is '3.2' do
+ it 'evaluates expressions left to right when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:a, :b, :c, :d]
+ end
+
+ it 'evaluates expressions left to right when assignment with a nested compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ ((ScratchPad << :a; m)::A, foo), bar = [(ScratchPad << :b; :b)]
+ ScratchPad.recorded.should == [:a, :b]
+ end
+
+ it 'evaluates expressions left to right when assignment with deeply nested compounded constants' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :a; m)::A,
+ ((ScratchPad << :b; m)::B,
+ ((ScratchPad << :c; m)::C, (ScratchPad << :d; m)::D),
+ (ScratchPad << :e; m)::E),
+ (ScratchPad << :f; m)::F = (ScratchPad << :value; :value)
+
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
+ end
+ end
+ end
+
+ context 'when assignment with method call and receiver is self' do
+ it 'assigns values correctly when assignment with accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+
+ def assign(v1, v2)
+ self.a, self.b = v1, v2
+ end
+ end
+
+ object.assign :v1, :v2
+ object.a.should == :v1
+ object.b.should == :v2
+ end
+
+ it 'evaluates expressions right to left when assignment with a nested accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+
+ def assign(v1, v2)
+ (self.a, self.b), c = [v1, v2], nil
+ end
+ end
+
+ object.assign :v1, :v2
+ object.a.should == :v1
+ object.b.should == :v2
+ end
+
+ it 'assigns values correctly when assignment with a #[]=' do
+ object = Object.new
+ class << object
+ def []=(key, v)
+ @h ||= {}
+ @h[key] = v
+ end
+
+ def [](key)
+ (@h || {})[key]
+ end
+
+ def assign(k1, v1, k2, v2)
+ self[k1], self[k2] = v1, v2
+ end
+ end
+
+ object.assign :k1, :v1, :k2, :v2
+ object[:k1].should == :v1
+ object[:k2].should == :v2
+ end
+
+ it 'assigns values correctly when assignment with a nested #[]=' do
+ object = Object.new
+ class << object
+ def []=(key, v)
+ @h ||= {}
+ @h[key] = v
+ end
+
+ def [](key)
+ (@h || {})[key]
+ end
+
+ def assign(k1, v1, k2, v2)
+ (self[k1], self[k2]), c = [v1, v2], nil
+ end
+ end
+
+ object.assign :k1, :v1, :k2, :v2
+ object[:k1].should == :v1
+ object[:k2].should == :v2
+ end
+
+ it 'assigns values correctly when assignment with compounded constant' do
+ m = Module.new
+ m.module_exec do
+ self::A, self::B = :v1, :v2
+ end
+
+ m::A.should == :v1
+ m::B.should == :v2
+ end
+
+ it 'assigns values correctly when assignment with a nested compounded constant' do
+ m = Module.new
+ m.module_exec do
+ (self::A, self::B), c = [:v1, :v2], nil
+ end
+
+ m::A.should == :v1
+ m::B.should == :v2
+ end
+ end
+end
diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb
index cfa612b93a..3262f09dd5 100644
--- a/spec/ruby/language/case_spec.rb
+++ b/spec/ruby/language/case_spec.rb
@@ -415,6 +415,19 @@ describe "The 'case'-construct" do
self.test("bar").should == false
self.test(true).should == true
end
+
+ it "warns if there are identical when clauses" do
+ -> {
+ eval <<~RUBY
+ case 1
+ when 2
+ :foo
+ when 2
+ :bar
+ end
+ RUBY
+ }.should complain(/warning: duplicated .when' clause with line \d+ is ignored/, verbose: true)
+ end
end
describe "The 'case'-construct with no target expression" do
diff --git a/spec/ruby/language/ensure_spec.rb b/spec/ruby/language/ensure_spec.rb
index 175222c86e..16e626b4d0 100644
--- a/spec/ruby/language/ensure_spec.rb
+++ b/spec/ruby/language/ensure_spec.rb
@@ -335,7 +335,7 @@ describe "An ensure block inside 'do end' block" do
begin
raise "oops"
ensure
- return caller(0, 2)
+ return caller(0, 2) # rubocop:disable Lint/EnsureReturn
end
end
line = __LINE__
diff --git a/spec/ruby/language/if_spec.rb b/spec/ruby/language/if_spec.rb
index a5da696000..70c847d830 100644
--- a/spec/ruby/language/if_spec.rb
+++ b/spec/ruby/language/if_spec.rb
@@ -305,6 +305,15 @@ describe "The if expression" do
6.times(&b)
ScratchPad.recorded.should == [4, 5, 4, 5]
end
+
+ it "warns when Integer literals are used instead of predicates" do
+ -> {
+ eval <<~RUBY
+ 10.times { |i| ScratchPad << i if 4..5 }
+ RUBY
+ }.should complain(/warning: integer literal in flip-flop/, verbose: true)
+ ScratchPad.recorded.should == []
+ end
end
describe "when a branch syntactically does not return a value" do
diff --git a/spec/ruby/language/string_spec.rb b/spec/ruby/language/string_spec.rb
index 1a1cd35850..083a7f5db5 100644
--- a/spec/ruby/language/string_spec.rb
+++ b/spec/ruby/language/string_spec.rb
@@ -231,9 +231,16 @@ describe "Ruby String literals" do
ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files.rb")).chomp.should == "true"
end
- it "produce different objects for literals with the same content in different files if the other file doesn't have the comment" do
- frozen_string_literal = "test".frozen? && "test".equal?("test")
- ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_no_comment.rb")).chomp.should == (!frozen_string_literal).to_s
+ guard -> { !(eval("'test'").frozen? && "test".equal?("test")) } do
+ it "produces different objects for literals with the same content in different files if the other file doesn't have the comment and String literals aren't frozen by default" do
+ ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_no_comment.rb")).chomp.should == "true"
+ end
+ end
+
+ guard -> { eval("'test'").frozen? && "test".equal?("test") } do
+ it "produces the same objects for literals with the same content in different files if the other file doesn't have the comment and String literals are frozen by default" do
+ ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_no_comment.rb")).chomp.should == "false"
+ end
end
it "produce different objects for literals with the same content in different files if they have different encodings" do
diff --git a/spec/ruby/library/io-wait/wait_spec.rb b/spec/ruby/library/io-wait/wait_spec.rb
index 3861281277..fc07c6a8d9 100644
--- a/spec/ruby/library/io-wait/wait_spec.rb
+++ b/spec/ruby/library/io-wait/wait_spec.rb
@@ -48,25 +48,18 @@ describe "IO#wait" do
end
it "waits for the READABLE event to be ready" do
- queue = Queue.new
- thread = Thread.new { queue.pop; sleep 1; @w.write('data to read') };
+ @r.wait(IO::READABLE, 0).should == nil
- queue.push('signal');
- @r.wait(IO::READABLE, 2).should_not == nil
-
- thread.join
+ @w.write('data to read')
+ @r.wait(IO::READABLE, 0).should_not == nil
end
it "waits for the WRITABLE event to be ready" do
written_bytes = IOWaitSpec.exhaust_write_buffer(@w)
+ @w.wait(IO::WRITABLE, 0).should == nil
- queue = Queue.new
- thread = Thread.new { queue.pop; sleep 1; @r.read(written_bytes) };
-
- queue.push('signal');
- @w.wait(IO::WRITABLE, 2).should_not == nil
-
- thread.join
+ @r.read(written_bytes)
+ @w.wait(IO::WRITABLE, 0).should_not == nil
end
it "returns nil when the READABLE event is not ready during the timeout" do
@@ -89,6 +82,24 @@ describe "IO#wait" do
-> { @w.wait(-1, 0) }.should raise_error(ArgumentError, "Events must be positive integer!")
end
end
+
+ it "changes thread status to 'sleep' when waits for READABLE event" do
+ t = Thread.new { @r.wait(IO::READABLE, 10) }
+ sleep 1
+ t.status.should == 'sleep'
+ t.kill
+ t.join # Thread#kill doesn't wait for the thread to end
+ end
+
+ it "changes thread status to 'sleep' when waits for WRITABLE event" do
+ written_bytes = IOWaitSpec.exhaust_write_buffer(@w)
+
+ t = Thread.new { @w.wait(IO::WRITABLE, 10) }
+ sleep 1
+ t.status.should == 'sleep'
+ t.kill
+ t.join # Thread#kill doesn't wait for the thread to end
+ end
end
context "[timeout, mode] passed" do
diff --git a/spec/ruby/library/net-http/httpresponse/inspect_spec.rb b/spec/ruby/library/net-http/httpresponse/inspect_spec.rb
index 23b6bff581..43071ec8cd 100644
--- a/spec/ruby/library/net-http/httpresponse/inspect_spec.rb
+++ b/spec/ruby/library/net-http/httpresponse/inspect_spec.rb
@@ -8,7 +8,7 @@ describe "Net::HTTPResponse#inspect" do
res.inspect.should == "#<Net::HTTPUnknownResponse ??? test response readbody=false>"
res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
- socket = Net::BufferedIO.new(StringIO.new(+"test body"))
+ socket = Net::BufferedIO.new(StringIO.new("test body"))
res.reading_body(socket, true) {}
res.inspect.should == "#<Net::HTTPUnknownResponse ??? test response readbody=true>"
end
diff --git a/spec/ruby/library/net-http/httpresponse/read_body_spec.rb b/spec/ruby/library/net-http/httpresponse/read_body_spec.rb
index 61a576d812..4530a26bfc 100644
--- a/spec/ruby/library/net-http/httpresponse/read_body_spec.rb
+++ b/spec/ruby/library/net-http/httpresponse/read_body_spec.rb
@@ -5,7 +5,7 @@ require 'stringio'
describe "Net::HTTPResponse#read_body" do
before :each do
@res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
- @socket = Net::BufferedIO.new(StringIO.new(+"test body"))
+ @socket = Net::BufferedIO.new(StringIO.new("test body"))
end
describe "when passed no arguments" do
diff --git a/spec/ruby/library/net-http/httpresponse/reading_body_spec.rb b/spec/ruby/library/net-http/httpresponse/reading_body_spec.rb
index b9ab112c96..637a2806f8 100644
--- a/spec/ruby/library/net-http/httpresponse/reading_body_spec.rb
+++ b/spec/ruby/library/net-http/httpresponse/reading_body_spec.rb
@@ -5,7 +5,7 @@ require "stringio"
describe "Net::HTTPResponse#reading_body" do
before :each do
@res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
- @socket = Net::BufferedIO.new(StringIO.new(+"test body"))
+ @socket = Net::BufferedIO.new(StringIO.new("test body"))
end
describe "when body_allowed is true" do
diff --git a/spec/ruby/library/net-http/httpresponse/shared/body.rb b/spec/ruby/library/net-http/httpresponse/shared/body.rb
index f35ca3200c..618e3936fb 100644
--- a/spec/ruby/library/net-http/httpresponse/shared/body.rb
+++ b/spec/ruby/library/net-http/httpresponse/shared/body.rb
@@ -3,7 +3,7 @@ require 'stringio'
describe :net_httpresponse_body, shared: true do
before :each do
@res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
- @socket = Net::BufferedIO.new(StringIO.new(+"test body"))
+ @socket = Net::BufferedIO.new(StringIO.new("test body"))
end
it "returns the read body" do
diff --git a/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb
index df44a50afa..ea5e65da5c 100644
--- a/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb
@@ -18,7 +18,37 @@ describe "BasicSocket#read_nonblock" do
it "receives data after it's ready" do
IO.select([@r], nil, nil, 2)
- @r.recv_nonblock(5).should == "aaa"
+ @r.read_nonblock(5).should == "aaa"
+ end
+
+ platform_is_not :windows do
+ it 'returned data is binary encoded regardless of the external encoding' do
+ IO.select([@r], nil, nil, 2)
+ @r.read_nonblock(1).encoding.should == Encoding::BINARY
+
+ @w.send("bbb", 0, @r.getsockname)
+ @r.set_encoding(Encoding::ISO_8859_1)
+ IO.select([@r], nil, nil, 2)
+ buffer = @r.read_nonblock(3)
+ buffer.should == "bbb"
+ buffer.encoding.should == Encoding::BINARY
+ end
+ end
+
+ it 'replaces the content of the provided buffer without changing its encoding' do
+ buffer = "initial data".dup.force_encoding(Encoding::UTF_8)
+
+ IO.select([@r], nil, nil, 2)
+ @r.read_nonblock(3, buffer)
+ buffer.should == "aaa"
+ buffer.encoding.should == Encoding::UTF_8
+
+ @w.send("bbb", 0, @r.getsockname)
+ @r.set_encoding(Encoding::ISO_8859_1)
+ IO.select([@r], nil, nil, 2)
+ @r.read_nonblock(3, buffer)
+ buffer.should == "bbb"
+ buffer.encoding.should == Encoding::UTF_8
end
platform_is :linux do
diff --git a/spec/ruby/library/socket/basicsocket/read_spec.rb b/spec/ruby/library/socket/basicsocket/read_spec.rb
new file mode 100644
index 0000000000..ba9de7d5cf
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/read_spec.rb
@@ -0,0 +1,47 @@
+require_relative '../spec_helper'
+require_relative '../fixtures/classes'
+
+describe "BasicSocket#read" do
+ SocketSpecs.each_ip_protocol do |family, ip_address|
+ before :each do
+ @r = Socket.new(family, :DGRAM)
+ @w = Socket.new(family, :DGRAM)
+
+ @r.bind(Socket.pack_sockaddr_in(0, ip_address))
+ @w.send("aaa", 0, @r.getsockname)
+ end
+
+ after :each do
+ @r.close unless @r.closed?
+ @w.close unless @w.closed?
+ end
+
+ it "receives data after it's ready" do
+ @r.read(3).should == "aaa"
+ end
+
+ it 'returned data is binary encoded regardless of the external encoding' do
+ @r.read(3).encoding.should == Encoding::BINARY
+
+ @w.send("bbb", 0, @r.getsockname)
+ @r.set_encoding(Encoding::UTF_8)
+ buffer = @r.read(3)
+ buffer.should == "bbb"
+ buffer.encoding.should == Encoding::BINARY
+ end
+
+ it 'replaces the content of the provided buffer without changing its encoding' do
+ buffer = "initial data".dup.force_encoding(Encoding::UTF_8)
+
+ @r.read(3, buffer)
+ buffer.should == "aaa"
+ buffer.encoding.should == Encoding::UTF_8
+
+ @w.send("bbb", 0, @r.getsockname)
+ @r.set_encoding(Encoding::ISO_8859_1)
+ @r.read(3, buffer)
+ buffer.should == "bbb"
+ buffer.encoding.should == Encoding::UTF_8
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/fcntl_spec.rb b/spec/ruby/library/stringio/fcntl_spec.rb
index f252d5e738..a78004d868 100644
--- a/spec/ruby/library/stringio/fcntl_spec.rb
+++ b/spec/ruby/library/stringio/fcntl_spec.rb
@@ -3,6 +3,6 @@ require_relative 'fixtures/classes'
describe "StringIO#fcntl" do
it "raises a NotImplementedError" do
- -> { StringIO.new(+"boom").fcntl }.should raise_error(NotImplementedError)
+ -> { StringIO.new("boom").fcntl }.should raise_error(NotImplementedError)
end
end
diff --git a/spec/ruby/library/stringio/initialize_spec.rb b/spec/ruby/library/stringio/initialize_spec.rb
index d1dff590bb..ad067a0be1 100644
--- a/spec/ruby/library/stringio/initialize_spec.rb
+++ b/spec/ruby/library/stringio/initialize_spec.rb
@@ -172,7 +172,7 @@ end
# NOTE: Synchronise with core/io/new_spec.rb (core/io/shared/new.rb)
describe "StringIO#initialize when passed keyword arguments" do
it "sets the mode based on the passed :mode option" do
- io = StringIO.new(+"example", "r")
+ io = StringIO.new("example", "r")
io.closed_read?.should be_false
io.closed_write?.should be_true
end
diff --git a/spec/ruby/library/stringio/read_nonblock_spec.rb b/spec/ruby/library/stringio/read_nonblock_spec.rb
index 8b78b1b0e4..74736f7792 100644
--- a/spec/ruby/library/stringio/read_nonblock_spec.rb
+++ b/spec/ruby/library/stringio/read_nonblock_spec.rb
@@ -33,7 +33,7 @@ end
describe "StringIO#read_nonblock" do
it "accepts an exception option" do
- stringio = StringIO.new(+'foo')
+ stringio = StringIO.new('foo')
stringio.read_nonblock(3, exception: false).should == 'foo'
end
diff --git a/spec/ruby/library/stringio/reopen_spec.rb b/spec/ruby/library/stringio/reopen_spec.rb
index 151bb58c6f..7021ff17e5 100644
--- a/spec/ruby/library/stringio/reopen_spec.rb
+++ b/spec/ruby/library/stringio/reopen_spec.rb
@@ -3,11 +3,11 @@ require_relative 'fixtures/classes'
describe "StringIO#reopen when passed [Object, Integer]" do
before :each do
- @io = StringIO.new(+"example")
+ @io = StringIO.new("example")
end
it "reopens self with the passed Object in the passed mode" do
- @io.reopen(+"reopened", IO::RDONLY)
+ @io.reopen("reopened", IO::RDONLY)
@io.closed_read?.should be_false
@io.closed_write?.should be_true
@io.string.should == "reopened"
@@ -51,11 +51,11 @@ end
describe "StringIO#reopen when passed [Object, Object]" do
before :each do
- @io = StringIO.new(+"example")
+ @io = StringIO.new("example")
end
it "reopens self with the passed Object in the passed mode" do
- @io.reopen(+"reopened", "r")
+ @io.reopen("reopened", "r")
@io.closed_read?.should be_false
@io.closed_write?.should be_true
@io.string.should == "reopened"
@@ -83,7 +83,7 @@ describe "StringIO#reopen when passed [Object, Object]" do
it "tries to convert the passed Object to a String using #to_str" do
obj = mock("to_str")
- obj.should_receive(:to_str).and_return(+"to_str")
+ obj.should_receive(:to_str).and_return("to_str")
@io.reopen(obj, "r")
@io.string.should == "to_str"
end
@@ -107,7 +107,7 @@ describe "StringIO#reopen when passed [Object, Object]" do
it "tries to convert the passed mode Object to an Integer using #to_str" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return("r")
- @io.reopen(+"reopened", obj)
+ @io.reopen("reopened", obj)
@io.closed_read?.should be_false
@io.closed_write?.should be_true
@io.string.should == "reopened"
@@ -128,7 +128,7 @@ end
describe "StringIO#reopen when passed [String]" do
before :each do
- @io = StringIO.new(+"example")
+ @io = StringIO.new("example")
end
it "reopens self with the passed String in read-write mode" do
@@ -157,7 +157,7 @@ end
describe "StringIO#reopen when passed [Object]" do
before :each do
- @io = StringIO.new(+"example")
+ @io = StringIO.new("example")
end
it "raises a TypeError when passed an Object that can't be converted to a StringIO" do
@@ -180,7 +180,7 @@ end
describe "StringIO#reopen when passed no arguments" do
before :each do
- @io = StringIO.new(+"example\nsecond line")
+ @io = StringIO.new("example\nsecond line")
end
it "resets self's mode to read-write" do
@@ -208,7 +208,7 @@ end
# for details.
describe "StringIO#reopen" do
before :each do
- @io = StringIO.new(+'hello','a')
+ @io = StringIO.new(+'hello', 'a')
end
# TODO: find out if this is really a bug
diff --git a/spec/ruby/optional/capi/ext/gc_spec.c b/spec/ruby/optional/capi/ext/gc_spec.c
index 7dd0b87655..1392bc6ee6 100644
--- a/spec/ruby/optional/capi/ext/gc_spec.c
+++ b/spec/ruby/optional/capi/ext/gc_spec.c
@@ -8,7 +8,12 @@ extern "C" {
VALUE registered_tagged_value;
VALUE registered_reference_value;
VALUE registered_before_rb_gc_register_address;
-VALUE registered_before_rb_global_variable;
+VALUE registered_before_rb_global_variable_string;
+VALUE registered_before_rb_global_variable_bignum;
+VALUE registered_before_rb_global_variable_float;
+VALUE registered_after_rb_global_variable_string;
+VALUE registered_after_rb_global_variable_bignum;
+VALUE registered_after_rb_global_variable_float;
VALUE rb_gc_register_address_outside_init;
static VALUE registered_tagged_address(VALUE self) {
@@ -23,8 +28,28 @@ static VALUE get_registered_before_rb_gc_register_address(VALUE self) {
return registered_before_rb_gc_register_address;
}
-static VALUE get_registered_before_rb_global_variable(VALUE self) {
- return registered_before_rb_global_variable;
+static VALUE get_registered_before_rb_global_variable_string(VALUE self) {
+ return registered_before_rb_global_variable_string;
+}
+
+static VALUE get_registered_before_rb_global_variable_bignum(VALUE self) {
+ return registered_before_rb_global_variable_bignum;
+}
+
+static VALUE get_registered_before_rb_global_variable_float(VALUE self) {
+ return registered_before_rb_global_variable_float;
+}
+
+static VALUE get_registered_after_rb_global_variable_string(VALUE self) {
+ return registered_after_rb_global_variable_string;
+}
+
+static VALUE get_registered_after_rb_global_variable_bignum(VALUE self) {
+ return registered_after_rb_global_variable_bignum;
+}
+
+static VALUE get_registered_after_rb_global_variable_float(VALUE self) {
+ return registered_after_rb_global_variable_float;
}
static VALUE gc_spec_rb_gc_register_address(VALUE self) {
@@ -71,17 +96,34 @@ void Init_gc_spec(void) {
rb_gc_register_address(&registered_tagged_value);
rb_gc_register_address(&registered_reference_value);
rb_gc_register_address(&registered_before_rb_gc_register_address);
- rb_global_variable(&registered_before_rb_global_variable);
+ rb_global_variable(&registered_before_rb_global_variable_string);
+ rb_global_variable(&registered_before_rb_global_variable_bignum);
+ rb_global_variable(&registered_before_rb_global_variable_float);
registered_tagged_value = INT2NUM(10);
registered_reference_value = rb_str_new2("Globally registered data");
registered_before_rb_gc_register_address = rb_str_new_cstr("registered before rb_gc_register_address()");
- registered_before_rb_global_variable = rb_str_new_cstr("registered before rb_global_variable()");
+
+ registered_before_rb_global_variable_string = rb_str_new_cstr("registered before rb_global_variable()");
+ registered_before_rb_global_variable_bignum = LL2NUM(INT64_MAX);
+ registered_before_rb_global_variable_float = DBL2NUM(3.14);
+
+ registered_after_rb_global_variable_string = rb_str_new_cstr("registered after rb_global_variable()");
+ rb_global_variable(&registered_after_rb_global_variable_string);
+ registered_after_rb_global_variable_bignum = LL2NUM(INT64_MAX);
+ rb_global_variable(&registered_after_rb_global_variable_bignum);
+ registered_after_rb_global_variable_float = DBL2NUM(6.28);
+ rb_global_variable(&registered_after_rb_global_variable_float);
rb_define_method(cls, "registered_tagged_address", registered_tagged_address, 0);
rb_define_method(cls, "registered_reference_address", registered_reference_address, 0);
rb_define_method(cls, "registered_before_rb_gc_register_address", get_registered_before_rb_gc_register_address, 0);
- rb_define_method(cls, "registered_before_rb_global_variable", get_registered_before_rb_global_variable, 0);
+ rb_define_method(cls, "registered_before_rb_global_variable_string", get_registered_before_rb_global_variable_string, 0);
+ rb_define_method(cls, "registered_before_rb_global_variable_bignum", get_registered_before_rb_global_variable_bignum, 0);
+ rb_define_method(cls, "registered_before_rb_global_variable_float", get_registered_before_rb_global_variable_float, 0);
+ rb_define_method(cls, "registered_after_rb_global_variable_string", get_registered_after_rb_global_variable_string, 0);
+ rb_define_method(cls, "registered_after_rb_global_variable_bignum", get_registered_after_rb_global_variable_bignum, 0);
+ rb_define_method(cls, "registered_after_rb_global_variable_float", get_registered_after_rb_global_variable_float, 0);
rb_define_method(cls, "rb_gc_register_address", gc_spec_rb_gc_register_address, 0);
rb_define_method(cls, "rb_gc_unregister_address", gc_spec_rb_gc_unregister_address, 0);
rb_define_method(cls, "rb_gc_enable", gc_spec_rb_gc_enable, 0);
diff --git a/spec/ruby/optional/capi/gc_spec.rb b/spec/ruby/optional/capi/gc_spec.rb
index d76ea7394f..aaced56483 100644
--- a/spec/ruby/optional/capi/gc_spec.rb
+++ b/spec/ruby/optional/capi/gc_spec.rb
@@ -27,9 +27,36 @@ describe "CApiGCSpecs" do
end
describe "rb_global_variable" do
- it "keeps the value alive even if the value is assigned after rb_global_variable() is called" do
+ before :all do
GC.start
- @f.registered_before_rb_global_variable.should == "registered before rb_global_variable()"
+ end
+
+ describe "keeps the value alive even if the value is assigned after rb_global_variable() is called" do
+ it "for a string" do
+ @f.registered_before_rb_global_variable_string.should == "registered before rb_global_variable()"
+ end
+
+ it "for a bignum" do
+ @f.registered_before_rb_global_variable_bignum.should == 2**63 - 1
+ end
+
+ it "for a Float" do
+ @f.registered_before_rb_global_variable_float.should == 3.14
+ end
+ end
+
+ describe "keeps the value alive when the value is assigned before rb_global_variable() is called" do
+ it "for a string" do
+ @f.registered_after_rb_global_variable_string.should == "registered after rb_global_variable()"
+ end
+
+ it "for a bignum" do
+ @f.registered_after_rb_global_variable_bignum.should == 2**63 - 1
+ end
+
+ it "for a Float" do
+ @f.registered_after_rb_global_variable_float.should == 6.28
+ end
end
end