1require_relative '../fixtures/classes'
2
3describe :symbol_slice, shared: true do
4  describe "with an Integer index" do
5    it "returns the character code of the element at the index" do
6      :symbol.send(@method, 1).should == ?y
7    end
8
9    it "returns nil if the index starts from the end and is greater than the length" do
10        :symbol.send(@method, -10).should be_nil
11    end
12
13    it "returns nil if the index is greater than the length" do
14      :symbol.send(@method, 42).should be_nil
15    end
16  end
17
18  describe "with an Integer index and length" do
19    describe "and a positive index and length" do
20      it "returns a slice" do
21        :symbol.send(@method, 1,3).should == "ymb"
22      end
23
24      it "returns a blank slice if the length is 0" do
25        :symbol.send(@method, 0,0).should == ""
26        :symbol.send(@method, 1,0).should == ""
27      end
28
29      it "returns a slice of all remaining characters if the given length is greater than the actual length" do
30        :symbol.send(@method, 1,100).should == "ymbol"
31      end
32
33      it "returns nil if the index is greater than the length" do
34        :symbol.send(@method, 10,1).should be_nil
35      end
36    end
37
38    describe "and a positive index and negative length" do
39      it "returns nil" do
40        :symbol.send(@method, 0,-1).should be_nil
41        :symbol.send(@method, 1,-1).should be_nil
42      end
43    end
44
45    describe "and a negative index and positive length" do
46      it "returns a slice starting from the end upto the length" do
47        :symbol.send(@method, -3,2).should == "bo"
48      end
49
50      it "returns a blank slice if the length is 0" do
51        :symbol.send(@method, -1,0).should == ""
52      end
53
54      it "returns a slice of all remaining characters if the given length is larger than the actual length" do
55        :symbol.send(@method, -4,100).should == "mbol"
56      end
57
58      it "returns nil if the index is past the start" do
59        :symbol.send(@method, -10,1).should be_nil
60      end
61    end
62
63    describe "and a negative index and negative length" do
64      it "returns nil" do
65        :symbol.send(@method, -1,-1).should be_nil
66      end
67    end
68
69    describe "and a Float length" do
70      it "converts the length to an Integer" do
71        :symbol.send(@method, 2,2.5).should == "mb"
72      end
73    end
74
75    describe "and a nil length" do
76      it "raises a TypeError" do
77        lambda { :symbol.send(@method, 1,nil) }.should raise_error(TypeError)
78      end
79    end
80
81    describe "and a length that cannot be converted into an Integer" do
82      it "raises a TypeError when given an Array" do
83        lambda { :symbol.send(@method, 1,Array.new) }.should raise_error(TypeError)
84      end
85
86      it "raises a TypeError when given an Hash" do
87        lambda { :symbol.send(@method, 1,Hash.new) }.should raise_error(TypeError)
88      end
89
90      it "raises a TypeError when given an Object" do
91        lambda { :symbol.send(@method, 1,Object.new) }.should raise_error(TypeError)
92      end
93    end
94  end
95
96  describe "with a Float index" do
97    it "converts the index to an Integer" do
98      :symbol.send(@method, 1.5).should == ?y
99    end
100  end
101
102  describe "with a nil index" do
103    it "raises a TypeError" do
104      lambda { :symbol.send(@method, nil) }.should raise_error(TypeError)
105    end
106  end
107
108  describe "with an index that cannot be converted into an Integer" do
109    it "raises a TypeError when given an Array" do
110      lambda { :symbol.send(@method, Array.new) }.should raise_error(TypeError)
111    end
112
113    it "raises a TypeError when given an Hash" do
114      lambda { :symbol.send(@method, Hash.new) }.should raise_error(TypeError)
115    end
116
117    it "raises a TypeError when given an Object" do
118      lambda { :symbol.send(@method, Object.new) }.should raise_error(TypeError)
119    end
120  end
121
122  describe "with a Range slice" do
123    describe "that is within bounds" do
124      it "returns a slice if both range values begin at the start and are within bounds" do
125        :symbol.send(@method, 1..4).should == "ymbo"
126      end
127
128      it "returns a slice if the first range value begins at the start and the last begins at the end" do
129        :symbol.send(@method, 1..-1).should == "ymbol"
130      end
131
132      it "returns a slice if the first range value begins at the end and the last begins at the end" do
133        :symbol.send(@method, -4..-1).should == "mbol"
134      end
135    end
136
137    describe "that is out of bounds" do
138      it "returns nil if the first range value begins past the end" do
139        :symbol.send(@method, 10..12).should be_nil
140      end
141
142      it "returns a blank string if the first range value is within bounds and the last range value is not" do
143        :symbol.send(@method, -2..-10).should == ""
144        :symbol.send(@method, 2..-10).should == ""
145      end
146
147      it "returns nil if the first range value starts from the end and is within bounds and the last value starts from the end and is greater than the length" do
148        :symbol.send(@method, -10..-12).should be_nil
149      end
150
151      it "returns nil if the first range value starts from the end and is out of bounds and the last value starts from the end and is less than the length" do
152        :symbol.send(@method, -10..-2).should be_nil
153      end
154    end
155
156    describe "with Float values" do
157      it "converts the first value to an Integer" do
158        :symbol.send(@method, 0.5..2).should == "sym"
159      end
160
161      it "converts the last value to an Integer" do
162        :symbol.send(@method, 0..2.5).should == "sym"
163      end
164    end
165  end
166
167  describe "with a Range subclass slice" do
168    it "returns a slice" do
169      range = SymbolSpecs::MyRange.new(1, 4)
170      :symbol.send(@method, range).should == "ymbo"
171    end
172  end
173
174  describe "with a Regex slice" do
175    describe "without a capture index" do
176      it "returns a string of the match" do
177        :symbol.send(@method, /[^bol]+/).should == "sym"
178      end
179
180      it "returns nil if the expression does not match" do
181        :symbol.send(@method, /0-9/).should be_nil
182      end
183
184      it "sets $~ to the MatchData if there is a match" do
185        :symbol.send(@method, /[^bol]+/)
186        $~[0].should == "sym"
187      end
188
189      it "does not set $~ if there if there is not a match" do
190        :symbol.send(@method, /[0-9]+/)
191        $~.should be_nil
192      end
193
194      it "returns a tainted string if the regexp is tainted" do
195        :symbol.send(@method, /./.taint).tainted?.should be_true
196      end
197
198      it "returns an untrusted string if the regexp is untrusted" do
199        :symbol.send(@method, /./.untrust).untrusted?.should be_true
200      end
201    end
202
203    describe "with a capture index" do
204      it "returns a string of the complete match if the capture index is 0" do
205        :symbol.send(@method, /(sy)(mb)(ol)/, 0).should == "symbol"
206      end
207
208      it "returns a string for the matched capture at the given index" do
209        :symbol.send(@method, /(sy)(mb)(ol)/, 1).should == "sy"
210        :symbol.send(@method, /(sy)(mb)(ol)/, -1).should == "ol"
211      end
212
213      it "returns nil if there is no capture for the index" do
214        :symbol.send(@method, /(sy)(mb)(ol)/, 4).should be_nil
215        :symbol.send(@method, /(sy)(mb)(ol)/, -4).should be_nil
216      end
217
218      it "converts the index to an Integer" do
219        :symbol.send(@method, /(sy)(mb)(ol)/, 1.5).should == "sy"
220      end
221
222      it "returns a tainted string if the regexp is tainted" do
223        :symbol.send(@method, /(.)/.taint, 1).tainted?.should be_true
224      end
225
226      it "returns an untrusted string if the regexp is untrusted" do
227        :symbol.send(@method, /(.)/.untrust, 1).untrusted?.should be_true
228      end
229
230      describe "and an index that cannot be converted to an Integer" do
231        it "raises a TypeError when given an Hash" do
232          lambda { :symbol.send(@method, /(sy)(mb)(ol)/, Hash.new) }.should raise_error(TypeError)
233        end
234
235        it "raises a TypeError when given an Array" do
236          lambda { :symbol.send(@method, /(sy)(mb)(ol)/, Array.new) }.should raise_error(TypeError)
237        end
238
239        it "raises a TypeError when given an Object" do
240          lambda { :symbol.send(@method, /(sy)(mb)(ol)/, Object.new) }.should raise_error(TypeError)
241        end
242      end
243
244      it "raises a TypeError if the index is nil" do
245        lambda { :symbol.send(@method, /(sy)(mb)(ol)/, nil) }.should raise_error(TypeError)
246      end
247
248      it "sets $~ to the MatchData if there is a match" do
249        :symbol.send(@method, /(sy)(mb)(ol)/, 0)
250        $~[0].should == "symbol"
251        $~[1].should == "sy"
252        $~[2].should == "mb"
253        $~[3].should == "ol"
254      end
255
256      it "does not set $~ to the MatchData if there is not a match" do
257        :symbol.send(@method, /0-9/, 0)
258        $~.should be_nil
259      end
260    end
261  end
262
263  describe "with a String slice" do
264    it "does not set $~" do
265      $~ = nil
266      :symbol.send(@method, "sym")
267      $~.should be_nil
268    end
269
270    it "returns a string if there is match" do
271      :symbol.send(@method, "ymb").should == "ymb"
272    end
273
274    it "returns nil if there is not a match" do
275      :symbol.send(@method, "foo").should be_nil
276    end
277  end
278end
279