summaryrefslogtreecommitdiff
path: root/spec/ruby/core/array/rotate_spec.rb
blob: 60dcc8b113207550712c7fd6f36f613207f757db (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
require_relative '../../spec_helper'
require_relative 'fixtures/classes'

describe "Array#rotate" do
  describe "when passed no argument" do
    it "returns a copy of the array with the first element moved at the end" do
      [1, 2, 3, 4, 5].rotate.should == [2, 3, 4, 5, 1]
    end
  end

  describe "with an argument n" do
    it "returns a copy of the array with the first (n % size) elements moved at the end" do
      a = [1, 2, 3, 4, 5]
      a.rotate(  2).should == [3, 4, 5, 1, 2]
      a.rotate( -1).should == [5, 1, 2, 3, 4]
      a.rotate(-21).should == [5, 1, 2, 3, 4]
      a.rotate( 13).should == [4, 5, 1, 2, 3]
      a.rotate(  0).should == a
    end

    it "coerces the argument using to_int" do
      [1, 2, 3].rotate(2.6).should == [3, 1, 2]

      obj = mock('integer_like')
      obj.should_receive(:to_int).and_return(2)
      [1, 2, 3].rotate(obj).should == [3, 1, 2]
    end

    it "raises a TypeError if not passed an integer-like argument" do
      -> {
        [1, 2].rotate(nil)
      }.should raise_error(TypeError)
      -> {
        [1, 2].rotate("4")
      }.should raise_error(TypeError)
    end
  end

  it "returns a copy of the array when its length is one or zero" do
    [1].rotate.should == [1]
    [1].rotate(2).should == [1]
    [1].rotate(-42).should == [1]
    [ ].rotate.should == []
    [ ].rotate(2).should == []
    [ ].rotate(-42).should == []
  end

  it "does not mutate the receiver" do
    -> {
      [].freeze.rotate
      [2].freeze.rotate(2)
      [1,2,3].freeze.rotate(-3)
    }.should_not raise_error
  end

  it "does not return self" do
    a = [1, 2, 3]
    a.rotate.should_not equal(a)
    a = []
    a.rotate(0).should_not equal(a)
  end

  it "does not return subclass instance for Array subclasses" do
    ArraySpecs::MyArray[1, 2, 3].rotate.should be_an_instance_of(Array)
  end
end

describe "Array#rotate!" do
  describe "when passed no argument" do
    it "moves the first element to the end and returns self" do
      a = [1, 2, 3, 4, 5]
      a.rotate!.should equal(a)
      a.should == [2, 3, 4, 5, 1]
    end
  end

  describe "with an argument n" do
    it "moves the first (n % size) elements at the end and returns self" do
      a = [1, 2, 3, 4, 5]
      a.rotate!(2).should equal(a)
      a.should == [3, 4, 5, 1, 2]
      a.rotate!(-12).should equal(a)
      a.should == [1, 2, 3, 4, 5]
      a.rotate!(13).should equal(a)
      a.should == [4, 5, 1, 2, 3]
    end

    it "coerces the argument using to_int" do
      [1, 2, 3].rotate!(2.6).should == [3, 1, 2]

      obj = mock('integer_like')
      obj.should_receive(:to_int).and_return(2)
      [1, 2, 3].rotate!(obj).should == [3, 1, 2]
    end

    it "raises a TypeError if not passed an integer-like argument" do
      -> {
        [1, 2].rotate!(nil)
      }.should raise_error(TypeError)
      -> {
        [1, 2].rotate!("4")
      }.should raise_error(TypeError)
    end
  end

  it "does nothing and returns self when the length is zero or one" do
    a = [1]
    a.rotate!.should equal(a)
    a.should == [1]
    a.rotate!(2).should equal(a)
    a.should == [1]
    a.rotate!(-21).should equal(a)
    a.should == [1]

    a = []
    a.rotate!.should equal(a)
    a.should == []
    a.rotate!(2).should equal(a)
    a.should == []
    a.rotate!(-21).should equal(a)
    a.should == []
  end

  it "raises a FrozenError on a frozen array" do
    -> { [1, 2, 3].freeze.rotate!(0) }.should raise_error(FrozenError)
    -> { [1].freeze.rotate!(42) }.should raise_error(FrozenError)
    -> { [].freeze.rotate! }.should raise_error(FrozenError)
  end
end