From 5a2835a5309a54397347f484500ff4df3004da93 Mon Sep 17 00:00:00 2001 From: Wender Freese Date: Wed, 6 Oct 2021 14:56:09 -0300 Subject: [PATCH 1/3] Add specs to cover the fix for [Bug #14266] --- library/set/clone_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 library/set/clone_spec.rb diff --git a/library/set/clone_spec.rb b/library/set/clone_spec.rb new file mode 100644 index 0000000000..3cd4932ea3 --- /dev/null +++ b/library/set/clone_spec.rb @@ -0,0 +1,17 @@ +require_relative '../../spec_helper' +require 'set' + +describe "Set#clone" do + ruby_version_is "3.0" do + it "does not freeze the new Set" do + set1 = Set[1, 2] + set1.freeze + set2 = set1.clone(freeze: false) + set1.frozen?.should == true + set2.frozen?.should == false + set2.add 3 + set1.should == Set[1, 2] + set2.should == Set[1, 2, 3] + end + end +end From 7972b72aa9d115880412a0dcbbcc1aebb2ab3c51 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 16 Oct 2021 13:37:01 +0200 Subject: [PATCH 2/3] Add spec for Kernel#clone(freeze: true/false) calling #initialize_clone(freeze: true/false) --- core/kernel/clone_spec.rb | 92 ++++++++++++++++++++++++++------- core/kernel/fixtures/classes.rb | 8 ++- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/core/kernel/clone_spec.rb b/core/kernel/clone_spec.rb index c18af4a490..f9daa2badc 100644 --- a/core/kernel/clone_spec.rb +++ b/core/kernel/clone_spec.rb @@ -28,27 +28,88 @@ def klass.allocate clone.class.should equal klass end - it "copies frozen state from the original" do - o2 = @obj.clone - @obj.freeze - o3 = @obj.clone + describe "with no arguments" do + it "copies frozen state from the original" do + o2 = @obj.clone + @obj.freeze + o3 = @obj.clone + + o2.should_not.frozen? + o3.should.frozen? + end - o2.should_not.frozen? - o3.should.frozen? + it 'copies frozen?' do + o = ''.freeze.clone + o.frozen?.should be_true + end end - ruby_version_is '3.0' do - it 'takes an freeze: true option to frozen copy' do - @obj.clone(freeze: true).should.frozen? + describe "with freeze: true" do + it 'makes a frozen copy if the original is frozen' do @obj.freeze @obj.clone(freeze: true).should.frozen? end + + ruby_version_is ''...'3.0' do + it 'does not freeze the copy even if the original is not frozen' do + @obj.clone(freeze: true).should_not.frozen? + end + + it "calls #initialize_clone with no kwargs" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: true) + ScratchPad.recorded.should == [obj, {}] + end + end + + ruby_version_is '3.0' do + it 'freezes the copy even if the original was not frozen' do + @obj.clone(freeze: true).should.frozen? + end + + it "calls #initialize_clone with kwargs freeze: true" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: true) + ScratchPad.recorded.should == [obj, { freeze: true }] + end + + it "calls #initialize_clone with kwargs freeze: true even if #initialize_clone only takes a single argument" do + obj = KernelSpecs::Clone.new + -> { obj.clone(freeze: true) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)') + end + end end - it 'takes an freeze: false option to not return frozen copy' do - @obj.clone(freeze: false).should_not.frozen? - @obj.freeze - @obj.clone(freeze: false).should_not.frozen? + describe "with freeze: false" do + it 'does not freeze the copy if the original is frozen' do + @obj.freeze + @obj.clone(freeze: false).should_not.frozen? + end + + it 'does not freeze the copy if the original is not frozen' do + @obj.clone(freeze: false).should_not.frozen? + end + + ruby_version_is ''...'3.0' do + it "calls #initialize_clone with no kwargs" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: false) + ScratchPad.recorded.should == [obj, {}] + end + end + + ruby_version_is '3.0' do + it "calls #initialize_clone with kwargs freeze: false" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: false) + ScratchPad.recorded.should == [obj, { freeze: false }] + end + + it "calls #initialize_clone with kwargs freeze: false even if #initialize_clone only takes a single argument" do + obj = KernelSpecs::Clone.new + -> { obj.clone(freeze: false) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)') + end + end end it "copies instance variables" do @@ -114,11 +175,6 @@ def bar cloned.bar.should == ['a'] end - it 'copies frozen?' do - o = ''.freeze.clone - o.frozen?.should be_true - end - ruby_version_is ''...'2.7' do it 'copies tainted?' do o = ''.taint.clone diff --git a/core/kernel/fixtures/classes.rb b/core/kernel/fixtures/classes.rb index 1bf5715c50..8de1407b92 100644 --- a/core/kernel/fixtures/classes.rb +++ b/core/kernel/fixtures/classes.rb @@ -288,7 +288,13 @@ def initialize_copy(other) class Clone def initialize_clone(other) - ScratchPad.record other.object_id + ScratchPad.record other + end + end + + class CloneFreeze + def initialize_clone(other, **kwargs) + ScratchPad.record([other, kwargs]) end end From a167809fffbef5edb54985e9b35d1f8b84342068 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 16 Oct 2021 13:41:21 +0200 Subject: [PATCH 3/3] Move Set spec since it is the behavior of Set#initialize_clone --- library/set/{clone_spec.rb => initialize_clone_spec.rb} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename library/set/{clone_spec.rb => initialize_clone_spec.rb} (74%) diff --git a/library/set/clone_spec.rb b/library/set/initialize_clone_spec.rb similarity index 74% rename from library/set/clone_spec.rb rename to library/set/initialize_clone_spec.rb index 3cd4932ea3..fda3f050ea 100644 --- a/library/set/clone_spec.rb +++ b/library/set/initialize_clone_spec.rb @@ -1,9 +1,9 @@ require_relative '../../spec_helper' require 'set' -describe "Set#clone" do +describe "Set#initialize_clone" do ruby_version_is "3.0" do - it "does not freeze the new Set" do + it "does not freeze the new Set when called from clone(freeze: false)" do set1 = Set[1, 2] set1.freeze set2 = set1.clone(freeze: false)