summaryrefslogtreecommitdiff
path: root/spec/ruby/core/kernel/shared/dup_clone.rb
blob: 116989958b32b2c9f2e053ba3bd05b9ddde4ad35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
class ObjectSpecDup
  def initialize()
    @obj = :original
  end

  attr_accessor :obj
end

class ObjectSpecDupInitCopy
  def initialize()
    @obj = :original
  end

  attr_accessor :obj, :original

  def initialize_copy(original)
    @obj = :init_copy
    @original = original
  end

  private :initialize_copy
end

describe :kernel_dup_clone, shared: true do
  it "returns a new object duplicated from the original" do
    o = ObjectSpecDup.new
    o2 = ObjectSpecDup.new

    o.obj = 10

    o3 = o.send(@method)

    o3.obj.should == 10
    o2.obj.should == :original
  end

  it "produces a shallow copy, contained objects are not recursively dupped" do
    o = ObjectSpecDup.new
    array = [1, 2]
    o.obj = array

    o2 = o.send(@method)
    o2.obj.should equal(o.obj)
  end

  it "calls #initialize_copy on the NEW object if available, passing in original object" do
    o = ObjectSpecDupInitCopy.new
    o2 = o.send(@method)

    o.obj.should == :original
    o2.obj.should == :init_copy
    o2.original.should equal(o)
  end

  it "preserves tainted state from the original" do
    o = ObjectSpecDupInitCopy.new
    o2 = o.send(@method)
    o.taint
    o3 = o.send(@method)

    o2.tainted?.should == false
    o3.tainted?.should == true
  end

  it "does not preserve the object_id" do
    o1 = ObjectSpecDupInitCopy.new
    old_object_id = o1.object_id
    o2 = o1.send(@method)
    o2.object_id.should_not == old_object_id
  end

  it "preserves untrusted state from the original" do
    o = ObjectSpecDupInitCopy.new
    o2 = o.send(@method)
    o.untrust
    o3 = o.send(@method)

    o2.untrusted?.should == false
    o3.untrusted?.should == true
  end

  ruby_version_is ''...'2.4' do
    it "raises a TypeError for NilClass" do
      lambda { nil.send(@method) }.should raise_error(TypeError)
    end

    it "raises a TypeError for TrueClass" do
      lambda { true.send(@method) }.should raise_error(TypeError)
    end

    it "raises a TypeError for FalseClass" do
      lambda { false.send(@method) }.should raise_error(TypeError)
    end

    it "raises a TypeError for Fixnum" do
      lambda { 1.send(@method) }.should raise_error(TypeError)
    end

    it "raises a TypeError for Symbol" do
      lambda { :my_symbol.send(@method) }.should raise_error(TypeError)
    end
  end

  ruby_version_is '2.4' do
    it "returns nil for NilClass" do
      nil.send(@method).should == nil
    end

    it "returns true for TrueClass" do
      true.send(@method).should == true
    end

    it "returns false for FalseClass" do
      false.send(@method).should == false
    end

    it "returns the same Integer for Integer" do
      1.send(@method).should == 1
    end

    it "returns the same Symbol for Symbol" do
      :my_symbol.send(@method).should == :my_symbol
    end
  end

  ruby_version_is ''...'2.5' do
    it "raises a TypeError for Complex" do
      c = Complex(1.3, 3.1)
      lambda { c.send(@method) }.should raise_error(TypeError)
    end

    it "raises a TypeError for Rational" do
      r = Rational(1, 3)
      lambda { r.send(@method) }.should raise_error(TypeError)
    end
  end

  ruby_version_is '2.5' do
    it "returns self for Complex" do
      c = Complex(1.3, 3.1)
      c.send(@method).should equal c
    end

    it "returns self for Rational" do
      r = Rational(1, 3)
      r.send(@method).should equal r
    end
  end
end