machete 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +9 -0
- data/README.md +78 -9
- data/VERSION +1 -1
- data/lib/machete/matchers.rb +128 -2
- data/lib/machete/parser.rb +382 -119
- data/lib/machete/parser.y +127 -49
- data/spec/machete/matchers_spec.rb +356 -0
- data/spec/machete/parser_spec.rb +202 -111
- metadata +5 -5
data/lib/machete/parser.y
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
class Machete::Parser
|
2
2
|
|
3
|
+
token INTEGER
|
4
|
+
token STRING
|
5
|
+
token ANY
|
6
|
+
token EVEN
|
7
|
+
token ODD
|
3
8
|
token METHOD_NAME
|
4
9
|
token CLASS_NAME
|
5
10
|
token SYMBOL
|
6
|
-
token INTEGER
|
7
|
-
token STRING
|
8
11
|
|
9
12
|
start expression
|
10
13
|
|
@@ -20,7 +23,9 @@ expression : primary
|
|
20
23
|
}
|
21
24
|
|
22
25
|
primary : node
|
26
|
+
| array
|
23
27
|
| literal
|
28
|
+
| any
|
24
29
|
|
25
30
|
node : CLASS_NAME {
|
26
31
|
result = NodeMatcher.new(val[0].to_sym)
|
@@ -33,55 +38,65 @@ attrs : attr
|
|
33
38
|
| attrs "," attr { result = val[0].merge(val[2]) }
|
34
39
|
|
35
40
|
attr : method_name "=" expression { result = { val[0].to_sym => val[2] } }
|
41
|
+
| method_name "^=" STRING {
|
42
|
+
result = {
|
43
|
+
val[0].to_sym => StartsWithMatcher.new(string_value(val[2]))
|
44
|
+
}
|
45
|
+
}
|
46
|
+
| method_name "$=" STRING {
|
47
|
+
result = {
|
48
|
+
val[0].to_sym => EndsWithMatcher.new(string_value(val[2]))
|
49
|
+
}
|
50
|
+
}
|
36
51
|
|
37
|
-
# Hack to overcome the fact that
|
38
|
-
# METHOD_NAME tokens
|
52
|
+
# Hack to overcome the fact that some tokens will lex as simple tokens, not
|
53
|
+
# METHOD_NAME tokens, and that "reserved words" will lex as separate kinds of
|
54
|
+
# tokens.
|
39
55
|
method_name : METHOD_NAME
|
56
|
+
| ANY
|
57
|
+
| EVEN
|
58
|
+
| ODD
|
59
|
+
| "*"
|
60
|
+
| "+"
|
40
61
|
| "<"
|
41
62
|
| ">"
|
63
|
+
| "^"
|
42
64
|
| "|"
|
43
65
|
|
66
|
+
array : "[" items_opt "]" { result = ArrayMatcher.new(val[1]) }
|
67
|
+
|
68
|
+
items_opt : /* empty */ { result = [] }
|
69
|
+
| items
|
70
|
+
|
71
|
+
items : item { result = [val[0]] }
|
72
|
+
| items "," item { result = val[0] << val[2] }
|
73
|
+
|
74
|
+
item : expression
|
75
|
+
| expression quantifier { result = Quantifier.new(val[0], *val[1]) }
|
76
|
+
|
77
|
+
quantifier : "*" { result = [0, nil, 1] }
|
78
|
+
| "+" { result = [1, nil, 1] }
|
79
|
+
| "?" { result = [0, 1, 1] }
|
80
|
+
| "{" INTEGER "}" {
|
81
|
+
result = [integer_value(val[1]), integer_value(val[1]), 1]
|
82
|
+
}
|
83
|
+
| "{" INTEGER "," "}" {
|
84
|
+
result = [integer_value(val[1]), nil, 1]
|
85
|
+
}
|
86
|
+
| "{" "," INTEGER "}" {
|
87
|
+
result = [0, integer_value(val[2]), 1]
|
88
|
+
}
|
89
|
+
| "{" INTEGER "," INTEGER "}" {
|
90
|
+
result = [integer_value(val[1]), integer_value(val[3]), 1]
|
91
|
+
}
|
92
|
+
| "{" EVEN "}" { result = [0, nil, 2] }
|
93
|
+
| "{" ODD "}" { result = [1, nil, 2] }
|
94
|
+
|
44
95
|
literal : SYMBOL { result = LiteralMatcher.new(val[0][1..-1].to_sym) }
|
45
|
-
| INTEGER {
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
val[0][2..-1].to_i(8)
|
50
|
-
elsif val[0] =~ /^0[dD]/
|
51
|
-
val[0][2..-1].to_i(10)
|
52
|
-
elsif val[0] =~ /^0[xX]/
|
53
|
-
val[0][2..-1].to_i(16)
|
54
|
-
elsif val[0] =~ /^0/
|
55
|
-
val[0][1..-1].to_i(8)
|
56
|
-
else
|
57
|
-
val[0].to_i
|
58
|
-
end
|
59
|
-
result = LiteralMatcher.new(value)
|
60
|
-
}
|
61
|
-
| STRING {
|
62
|
-
quote = val[0][0..0]
|
63
|
-
value = if quote == "'"
|
64
|
-
val[0][1..-2].gsub("\\\\", "\\").gsub("\\'", "'")
|
65
|
-
elsif quote == '"'
|
66
|
-
val[0][1..-2].
|
67
|
-
gsub("\\\\", "\\").
|
68
|
-
gsub('\\"', '"').
|
69
|
-
gsub("\\n", "\n").
|
70
|
-
gsub("\\t", "\t").
|
71
|
-
gsub("\\r", "\r").
|
72
|
-
gsub("\\f", "\f").
|
73
|
-
gsub("\\v", "\v").
|
74
|
-
gsub("\\a", "\a").
|
75
|
-
gsub("\\e", "\e").
|
76
|
-
gsub("\\b", "\b").
|
77
|
-
gsub("\\s", "\s").
|
78
|
-
gsub(/\\([0-7]{1,3})/) { $1.to_i(8).chr }.
|
79
|
-
gsub(/\\x([0-9a-fA-F]{1,2})/) { $1.to_i(16).chr }
|
80
|
-
else
|
81
|
-
raise "Unknown quote: #{quote.inspect}."
|
82
|
-
end
|
83
|
-
result = LiteralMatcher.new(value)
|
84
|
-
}
|
96
|
+
| INTEGER { result = LiteralMatcher.new(integer_value(val[0])) }
|
97
|
+
| STRING { result = LiteralMatcher.new(string_value(val[0])) }
|
98
|
+
|
99
|
+
any : ANY { result = AnyMatcher.new }
|
85
100
|
|
86
101
|
---- inner
|
87
102
|
|
@@ -98,7 +113,65 @@ end
|
|
98
113
|
|
99
114
|
private
|
100
115
|
|
101
|
-
|
116
|
+
def integer_value(value)
|
117
|
+
if value =~ /^0[bB]/
|
118
|
+
value[2..-1].to_i(2)
|
119
|
+
elsif value =~ /^0[oO]/
|
120
|
+
value[2..-1].to_i(8)
|
121
|
+
elsif value =~ /^0[dD]/
|
122
|
+
value[2..-1].to_i(10)
|
123
|
+
elsif value =~ /^0[xX]/
|
124
|
+
value[2..-1].to_i(16)
|
125
|
+
elsif value =~ /^0/
|
126
|
+
value[1..-1].to_i(8)
|
127
|
+
else
|
128
|
+
value.to_i
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def string_value(value)
|
133
|
+
quote = value[0..0]
|
134
|
+
if quote == "'"
|
135
|
+
value[1..-2].gsub("\\\\", "\\").gsub("\\'", "'")
|
136
|
+
elsif quote == '"'
|
137
|
+
value[1..-2].
|
138
|
+
gsub("\\\\", "\\").
|
139
|
+
gsub('\\"', '"').
|
140
|
+
gsub("\\n", "\n").
|
141
|
+
gsub("\\t", "\t").
|
142
|
+
gsub("\\r", "\r").
|
143
|
+
gsub("\\f", "\f").
|
144
|
+
gsub("\\v", "\v").
|
145
|
+
gsub("\\a", "\a").
|
146
|
+
gsub("\\e", "\e").
|
147
|
+
gsub("\\b", "\b").
|
148
|
+
gsub("\\s", "\s").
|
149
|
+
gsub(/\\([0-7]{1,3})/) { $1.to_i(8).chr }.
|
150
|
+
gsub(/\\x([0-9a-fA-F]{1,2})/) { $1.to_i(16).chr }
|
151
|
+
else
|
152
|
+
raise "Unknown quote: #{quote.inspect}."
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# "^" needs to be here because if it were among operators recognized by
|
157
|
+
# METHOD_NAME, "^=" would be recognized as two tokens.
|
158
|
+
SIMPLE_TOKENS = [
|
159
|
+
"|",
|
160
|
+
"<",
|
161
|
+
">",
|
162
|
+
",",
|
163
|
+
"=",
|
164
|
+
"^=",
|
165
|
+
"^",
|
166
|
+
"$=",
|
167
|
+
"[",
|
168
|
+
"]",
|
169
|
+
"*",
|
170
|
+
"+",
|
171
|
+
"?",
|
172
|
+
"{",
|
173
|
+
"}"
|
174
|
+
]
|
102
175
|
|
103
176
|
COMPLEX_TOKENS = [
|
104
177
|
# INTEGER needs to be before METHOD_NAME, otherwise e.g. "+1" would be
|
@@ -151,9 +224,14 @@ COMPLEX_TOKENS = [
|
|
151
224
|
)
|
152
225
|
/x
|
153
226
|
],
|
154
|
-
#
|
155
|
-
#
|
156
|
-
|
227
|
+
# ANY, EVEN and ODD need to be before METHOD_NAME, otherwise they would be
|
228
|
+
# recognized as method names.
|
229
|
+
[:ANY, /^any/],
|
230
|
+
[:EVEN, /^even/],
|
231
|
+
[:ODD, /^odd/],
|
232
|
+
# We exclude "*", "+", "<", ">", "^" and "|" from method names since they are
|
233
|
+
# lexed as simple tokens. This is because they have also other meanings in
|
234
|
+
# Machette patterns beside Ruby method names.
|
157
235
|
[
|
158
236
|
:METHOD_NAME,
|
159
237
|
/^
|
@@ -162,7 +240,7 @@ COMPLEX_TOKENS = [
|
|
162
240
|
[a-z_][a-zA-Z0-9_]*[?!=]?
|
163
241
|
|
|
164
242
|
# operator (sorted by length, then alphabetically)
|
165
|
-
(<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[
|
243
|
+
(<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&\-\/`~])
|
166
244
|
)
|
167
245
|
/x
|
168
246
|
],
|
@@ -1,6 +1,54 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
module Machete::Matchers
|
4
|
+
describe Quantifier do
|
5
|
+
before :each do
|
6
|
+
@quantifier = Quantifier.new(LiteralMatcher.new(42), 0, 100, 10)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "initialize" do
|
10
|
+
it "sets attributes correctly" do
|
11
|
+
@quantifier.matcher.should == LiteralMatcher.new(42)
|
12
|
+
@quantifier.min.should == 0
|
13
|
+
@quantifier.max.should == 100
|
14
|
+
@quantifier.step.should == 10
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "==" do
|
19
|
+
it "returns true when passed the same object" do
|
20
|
+
@quantifier.should == @quantifier
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns true when passed a Quantifier initialized with the same parameters" do
|
24
|
+
@quantifier.should == Quantifier.new(LiteralMatcher.new(42), 0, 100, 10)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns false when passed some random object" do
|
28
|
+
@quantifier.should_not == Object.new
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns false when passed a subclass of Quantifier initialized with the same parameters" do
|
32
|
+
class SubclassedQuantifier < Quantifier
|
33
|
+
end
|
34
|
+
|
35
|
+
@quantifier.should_not ==
|
36
|
+
SubclassedQuantifier.new(LiteralMatcher.new(42), 0, 100, 10)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns false when passed a Quantifier initialized with different parameters" do
|
40
|
+
@quantifier.should_not ==
|
41
|
+
Quantifier.new(LiteralMatcher.new(43), 0, 100, 10)
|
42
|
+
@quantifier.should_not ==
|
43
|
+
Quantifier.new(LiteralMatcher.new(42), 1, 100, 10)
|
44
|
+
@quantifier.should_not ==
|
45
|
+
Quantifier.new(LiteralMatcher.new(42), 0, 101, 10)
|
46
|
+
@quantifier.should_not ==
|
47
|
+
Quantifier.new(LiteralMatcher.new(42), 0, 100, 11)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
4
52
|
describe ChoiceMatcher do
|
5
53
|
before :each do
|
6
54
|
@alternatives = [
|
@@ -137,6 +185,183 @@ module Machete::Matchers
|
|
137
185
|
end
|
138
186
|
end
|
139
187
|
|
188
|
+
describe ArrayMatcher do
|
189
|
+
before :each do
|
190
|
+
@items = [
|
191
|
+
LiteralMatcher.new(42),
|
192
|
+
LiteralMatcher.new(43),
|
193
|
+
LiteralMatcher.new(44)
|
194
|
+
]
|
195
|
+
@matcher = ArrayMatcher.new(@items)
|
196
|
+
end
|
197
|
+
|
198
|
+
describe "initialize" do
|
199
|
+
it "sets attributes correctly" do
|
200
|
+
@matcher.items.should == @items
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "==" do
|
205
|
+
it "returns true when passed the same object" do
|
206
|
+
@matcher.should == @matcher
|
207
|
+
end
|
208
|
+
|
209
|
+
it "returns true when passed a ArrayMatcher initialized with the same parameters" do
|
210
|
+
@matcher.should == ArrayMatcher.new(@items)
|
211
|
+
end
|
212
|
+
|
213
|
+
it "returns false when passed some random object" do
|
214
|
+
@matcher.should_not == Object.new
|
215
|
+
end
|
216
|
+
|
217
|
+
it "returns false when passed a subclass of ArrayMatcher initialized with the same parameters" do
|
218
|
+
class SubclassedArrayMatcher < ArrayMatcher
|
219
|
+
end
|
220
|
+
|
221
|
+
@matcher.should_not == SubclassedArrayMatcher.new(@items)
|
222
|
+
end
|
223
|
+
|
224
|
+
it "returns false when passed a ArrayMatcher initialized with different parameters" do
|
225
|
+
@matcher.should_not == ArrayMatcher.new([
|
226
|
+
LiteralMatcher.new(45),
|
227
|
+
LiteralMatcher.new(46),
|
228
|
+
LiteralMatcher.new(47)
|
229
|
+
])
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe "matches?" do
|
234
|
+
it "works on matcher with no items" do
|
235
|
+
matcher = ArrayMatcher.new([])
|
236
|
+
|
237
|
+
matcher.matches?([]).should be_true
|
238
|
+
matcher.matches?([42]).should be_false
|
239
|
+
end
|
240
|
+
|
241
|
+
it "works on matcher with one item" do
|
242
|
+
matcher = ArrayMatcher.new([LiteralMatcher.new(42)])
|
243
|
+
|
244
|
+
matcher.matches?([]).should be_false
|
245
|
+
matcher.matches?([42]).should be_true
|
246
|
+
matcher.matches?([43]).should be_false
|
247
|
+
matcher.matches?([42, 43]).should be_false
|
248
|
+
end
|
249
|
+
|
250
|
+
it "works on matcher with many items" do
|
251
|
+
matcher = ArrayMatcher.new([
|
252
|
+
LiteralMatcher.new(42),
|
253
|
+
LiteralMatcher.new(43),
|
254
|
+
LiteralMatcher.new(44)
|
255
|
+
])
|
256
|
+
|
257
|
+
matcher.matches?([42, 43]).should be_false
|
258
|
+
matcher.matches?([42, 43, 44]).should be_true
|
259
|
+
matcher.matches?([43, 43, 44]).should be_false
|
260
|
+
matcher.matches?([42, 44, 44]).should be_false
|
261
|
+
matcher.matches?([42, 43, 45]).should be_false
|
262
|
+
matcher.matches?([42, 43, 44, 45]).should be_false
|
263
|
+
end
|
264
|
+
|
265
|
+
it "works on matcher with a bound quantifier" do
|
266
|
+
matcher = ArrayMatcher.new([
|
267
|
+
Quantifier.new(LiteralMatcher.new(42), 1, 2, 1)
|
268
|
+
])
|
269
|
+
|
270
|
+
matcher.matches?([]).should be_false
|
271
|
+
matcher.matches?([42]).should be_true
|
272
|
+
matcher.matches?([43]).should be_false
|
273
|
+
matcher.matches?([42, 42]).should be_true
|
274
|
+
matcher.matches?([43, 42]).should be_false
|
275
|
+
matcher.matches?([42, 43]).should be_false
|
276
|
+
matcher.matches?([42, 42, 42]).should be_false
|
277
|
+
end
|
278
|
+
|
279
|
+
it "works on matcher with a bound quantifier with a bigger step" do
|
280
|
+
matcher = ArrayMatcher.new([
|
281
|
+
Quantifier.new(LiteralMatcher.new(42), 1, 3, 2)
|
282
|
+
])
|
283
|
+
|
284
|
+
matcher.matches?([]).should be_false
|
285
|
+
matcher.matches?([42]).should be_true
|
286
|
+
matcher.matches?([43]).should be_false
|
287
|
+
matcher.matches?([42, 42]).should be_false
|
288
|
+
matcher.matches?([42, 42, 42]).should be_true
|
289
|
+
matcher.matches?([43, 42, 42]).should be_false
|
290
|
+
matcher.matches?([42, 43, 42]).should be_false
|
291
|
+
matcher.matches?([42, 42, 43]).should be_false
|
292
|
+
matcher.matches?([42, 42, 42, 42]).should be_false
|
293
|
+
end
|
294
|
+
|
295
|
+
it "works on matcher with a bound quantifier and some items" do
|
296
|
+
matcher = ArrayMatcher.new([
|
297
|
+
LiteralMatcher.new(42),
|
298
|
+
Quantifier.new(LiteralMatcher.new(43), 0, 1, 1),
|
299
|
+
LiteralMatcher.new(44)
|
300
|
+
])
|
301
|
+
|
302
|
+
matcher.matches?([42, 44]).should be_true
|
303
|
+
matcher.matches?([42, 43, 44]).should be_true
|
304
|
+
matcher.matches?([42, 44, 44]).should be_false
|
305
|
+
matcher.matches?([42, 43, 43, 44]).should be_false
|
306
|
+
end
|
307
|
+
|
308
|
+
it "works on matcher with an unbound quantifier" do
|
309
|
+
matcher = ArrayMatcher.new([
|
310
|
+
Quantifier.new(LiteralMatcher.new(42), 1, nil, 1)
|
311
|
+
])
|
312
|
+
|
313
|
+
matcher.matches?([]).should be_false
|
314
|
+
matcher.matches?([42]).should be_true
|
315
|
+
matcher.matches?([43]).should be_false
|
316
|
+
matcher.matches?([42, 42]).should be_true
|
317
|
+
matcher.matches?([43, 42]).should be_false
|
318
|
+
matcher.matches?([42, 43]).should be_false
|
319
|
+
matcher.matches?([42, 42, 42]).should be_true
|
320
|
+
matcher.matches?([43, 42, 42]).should be_false
|
321
|
+
matcher.matches?([42, 43, 42]).should be_false
|
322
|
+
matcher.matches?([42, 42, 43]).should be_false
|
323
|
+
end
|
324
|
+
|
325
|
+
it "works on matcher with an unbound quantifier with a bigger step" do
|
326
|
+
matcher = ArrayMatcher.new([
|
327
|
+
Quantifier.new(LiteralMatcher.new(42), 1, nil, 2)
|
328
|
+
])
|
329
|
+
|
330
|
+
matcher.matches?([]).should be_false
|
331
|
+
matcher.matches?([42]).should be_true
|
332
|
+
matcher.matches?([43]).should be_false
|
333
|
+
matcher.matches?([42, 42]).should be_false
|
334
|
+
matcher.matches?([42, 42, 42]).should be_true
|
335
|
+
matcher.matches?([43, 42, 42]).should be_false
|
336
|
+
matcher.matches?([42, 43, 42]).should be_false
|
337
|
+
matcher.matches?([42, 42, 43]).should be_false
|
338
|
+
end
|
339
|
+
|
340
|
+
it "works on matcher with an unbound quantifier and some items" do
|
341
|
+
matcher = ArrayMatcher.new([
|
342
|
+
LiteralMatcher.new(42),
|
343
|
+
Quantifier.new(LiteralMatcher.new(43), 0, nil, 1),
|
344
|
+
LiteralMatcher.new(44)
|
345
|
+
])
|
346
|
+
|
347
|
+
matcher.matches?([42, 44]).should be_true
|
348
|
+
matcher.matches?([42, 43, 44]).should be_true
|
349
|
+
matcher.matches?([42, 44, 44]).should be_false
|
350
|
+
matcher.matches?([42, 43, 43, 44]).should be_true
|
351
|
+
matcher.matches?([42, 44, 43, 44]).should be_false
|
352
|
+
matcher.matches?([42, 43, 44, 44]).should be_false
|
353
|
+
matcher.matches?([42, 43, 43, 43, 44]).should be_true
|
354
|
+
matcher.matches?([42, 44, 43, 43, 44]).should be_false
|
355
|
+
matcher.matches?([42, 43, 44, 43, 44]).should be_false
|
356
|
+
matcher.matches?([42, 43, 43, 44, 44]).should be_false
|
357
|
+
end
|
358
|
+
|
359
|
+
it "does not match some random object" do
|
360
|
+
@matcher.matches?(Object.new).should be_false
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
140
365
|
describe LiteralMatcher do
|
141
366
|
before :each do
|
142
367
|
@matcher = LiteralMatcher.new(42)
|
@@ -183,4 +408,135 @@ module Machete::Matchers
|
|
183
408
|
end
|
184
409
|
end
|
185
410
|
end
|
411
|
+
|
412
|
+
describe StartsWithMatcher do
|
413
|
+
before :each do
|
414
|
+
@matcher = StartsWithMatcher.new("abcd")
|
415
|
+
end
|
416
|
+
|
417
|
+
describe "initialize" do
|
418
|
+
it "sets attributes correctly" do
|
419
|
+
@matcher.prefix.should == "abcd"
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
describe "==" do
|
424
|
+
it "returns true when passed the same object" do
|
425
|
+
@matcher.should == @matcher
|
426
|
+
end
|
427
|
+
|
428
|
+
it "returns true when passed a StartsWithMatcher initialized with the same parameters" do
|
429
|
+
@matcher.should == StartsWithMatcher.new("abcd")
|
430
|
+
end
|
431
|
+
|
432
|
+
it "returns false when passed some random object" do
|
433
|
+
@matcher.should_not == Object.new
|
434
|
+
end
|
435
|
+
|
436
|
+
it "returns false when passed a subclass of StartsWithMatcher initialized with the same parameters" do
|
437
|
+
class SubclassedStartsWithMatcher < StartsWithMatcher
|
438
|
+
end
|
439
|
+
|
440
|
+
@matcher.should_not == SubclassedStartsWithMatcher.new("abcd")
|
441
|
+
end
|
442
|
+
|
443
|
+
it "returns false when passed a StartsWithMatcher initialized with different parameters" do
|
444
|
+
@matcher.should_not == StartsWithMatcher.new("efgh")
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
describe "matches?" do
|
449
|
+
it "matches a string starting with the prefix" do
|
450
|
+
@matcher.matches?("abcdefgh").should be_true
|
451
|
+
end
|
452
|
+
|
453
|
+
it "does not match a string not starting with the prefix" do
|
454
|
+
@matcher.matches?("efghijkl").should be_false
|
455
|
+
end
|
456
|
+
|
457
|
+
it "does not match some random object" do
|
458
|
+
@matcher.matches?(Object.new).should be_false
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
describe EndsWithMatcher do
|
464
|
+
before :each do
|
465
|
+
@matcher = EndsWithMatcher.new("abcd")
|
466
|
+
end
|
467
|
+
|
468
|
+
describe "initialize" do
|
469
|
+
it "sets attributes correctly" do
|
470
|
+
@matcher.suffix.should == "abcd"
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
describe "==" do
|
475
|
+
it "returns true when passed the same object" do
|
476
|
+
@matcher.should == @matcher
|
477
|
+
end
|
478
|
+
|
479
|
+
it "returns true when passed a EndsWithMatcher initialized with the same parameters" do
|
480
|
+
@matcher.should == EndsWithMatcher.new("abcd")
|
481
|
+
end
|
482
|
+
|
483
|
+
it "returns false when passed some random object" do
|
484
|
+
@matcher.should_not == Object.new
|
485
|
+
end
|
486
|
+
|
487
|
+
it "returns false when passed a subclass of EndsWithMatcher initialized with the same parameters" do
|
488
|
+
class SubclassedEndsWithMatcher < EndsWithMatcher
|
489
|
+
end
|
490
|
+
|
491
|
+
@matcher.should_not == SubclassedEndsWithMatcher.new("abcd")
|
492
|
+
end
|
493
|
+
|
494
|
+
it "returns false when passed a EndsWithMatcher initialized with different parameters" do
|
495
|
+
@matcher.should_not == EndsWithMatcher.new("efgh")
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
describe "matches?" do
|
500
|
+
it "matches a string ending with the suffix" do
|
501
|
+
@matcher.matches?("efghabcd").should be_true
|
502
|
+
end
|
503
|
+
|
504
|
+
it "does not match a string not ending with the suffix" do
|
505
|
+
@matcher.matches?("ijklefgh").should be_false
|
506
|
+
end
|
507
|
+
|
508
|
+
it "does not match some random object" do
|
509
|
+
@matcher.matches?(Object.new).should be_false
|
510
|
+
end
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
describe AnyMatcher do
|
515
|
+
before :each do
|
516
|
+
@matcher = AnyMatcher.new
|
517
|
+
end
|
518
|
+
|
519
|
+
describe "==" do
|
520
|
+
it "returns true when passed the same object" do
|
521
|
+
@matcher.should == @matcher
|
522
|
+
end
|
523
|
+
|
524
|
+
it "returns false when passed some random object" do
|
525
|
+
@matcher.should_not == Object.new
|
526
|
+
end
|
527
|
+
|
528
|
+
it "returns false when passed a subclass of AnyMatcher" do
|
529
|
+
class SubclassedAnyMatcher < AnyMatcher
|
530
|
+
end
|
531
|
+
|
532
|
+
@matcher.should_not == SubclassedAnyMatcher.new
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
describe "matches?" do
|
537
|
+
it "matches any object" do
|
538
|
+
@matcher.matches?(Object.new)
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
186
542
|
end
|