1/*
2 * Copyright 2001-2008 Artima, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.scalatest.matchers
17
18import org.scalatest._
19import org.scalatest.prop.Checkers
20import org.mockito.Mockito._
21import org.scalatest.mock.MockitoSugar
22
23class ShouldLogicalMatcherExprSpec extends Spec with ShouldMatchers with Checkers with MockitoSugar with ReturnsNormallyThrowsAssertion {
24
25  class Clown {
26    def hasBigRedNose = true
27  }
28
29  describe("Matcher expressions to the right of and") {
30    describe("(A plain-old matcher)") {
31      it("should not short-circuit if left matcher doesn't match") {
32
33        val mockClown = mock[Clown]
34
35        intercept[TestFailedException] {
36          "hi" should (have length (1) and { mockClown.hasBigRedNose; have length (2) })
37        }
38
39        verify(mockClown, times(1)).hasBigRedNose
40      }
41    }
42
43    describe("(have length N syntax)") {
44      it("should not short-circuit if left matcher doesn't match") {
45
46        val mockClown = mock[Clown]
47
48        intercept[TestFailedException] {
49          "hi" should (have length (1) and have length {mockClown.hasBigRedNose; 2})
50        }
51
52        verify(mockClown, times(1)).hasBigRedNose
53
54        intercept[TestFailedException] {
55          "hi" should (have length (1) and {mockClown.hasBigRedNose; have length 2})
56        }
57
58        verify(mockClown, times(2)).hasBigRedNose
59      }
60    }
61
62    describe("(not have length N syntax)") {
63      it("should not short-circuit if left matcher doesn't match") {
64
65        val mockClown = mock[Clown]
66
67        intercept[TestFailedException] {
68          "hi" should (have length (1) and not have length {mockClown.hasBigRedNose; 1})
69        }
70
71        verify(mockClown, times(1)).hasBigRedNose
72
73        intercept[TestFailedException] {
74          "hi" should (have length (1) and not {mockClown.hasBigRedNose; have length (1)})
75        }
76
77        verify(mockClown, times(2)).hasBigRedNose
78
79        intercept[TestFailedException] {
80          "hi" should (have length (1) and {mockClown.hasBigRedNose; not have length (1)})
81        }
82
83        verify(mockClown, times(3)).hasBigRedNose
84      }
85    }
86
87    describe("(have size N syntax)") {
88      it("should not short-circuit if left matcher doesn't match") {
89
90        val mockClown = mock[Clown]
91
92        intercept[TestFailedException] {
93          Array(1, 2) should (have size (1) and have size {mockClown.hasBigRedNose; 2})
94        }
95
96        verify(mockClown, times(1)).hasBigRedNose
97
98        intercept[TestFailedException] {
99          "hi" should (have size (1) and {mockClown.hasBigRedNose; have size 2})
100        }
101
102        verify(mockClown, times(2)).hasBigRedNose
103      }
104    }
105
106    describe("(not have size N syntax)") {
107      it("should not short-circuit if left matcher doesn't match") {
108
109        val mockClown = mock[Clown]
110
111        intercept[TestFailedException] {
112          Array(1, 2) should (have size (1) and not have size {mockClown.hasBigRedNose; 1})
113        }
114
115        verify(mockClown, times(1)).hasBigRedNose
116
117        intercept[TestFailedException] {
118          Array(1, 2) should (have size (1) and not {mockClown.hasBigRedNose; have size (1)})
119        }
120
121        verify(mockClown, times(2)).hasBigRedNose
122
123        intercept[TestFailedException] {
124          Array(1, 2) should (have size (1) and {mockClown.hasBigRedNose; not have size (1)})
125        }
126
127        verify(mockClown, times(3)).hasBigRedNose
128      }
129    }
130
131    describe("(equal N syntax)") {
132      it("should not short-circuit if left matcher doesn't match") {
133
134        val mockClown = mock[Clown]
135
136        intercept[TestFailedException] {
137          "hi" should (equal ("ho") and equal {mockClown.hasBigRedNose; "ho"})
138        }
139
140        verify(mockClown, times(1)).hasBigRedNose
141
142        intercept[TestFailedException] {
143          "hi" should (equal ("ho") and {mockClown.hasBigRedNose; equal ("ho")})
144        }
145
146        verify(mockClown, times(2)).hasBigRedNose
147      }
148    }
149  }
150
151  describe("(not equal N syntax)") {
152    it("should not short-circuit if left matcher doesn't match") {
153
154      val mockClown = mock[Clown]
155
156      intercept[TestFailedException] {
157        "hi" should (equal ("ho") and not equal {mockClown.hasBigRedNose; "ho"})
158      }
159
160      verify(mockClown, times(1)).hasBigRedNose
161
162      intercept[TestFailedException] {
163        "hi" should (equal ("ho") and {mockClown.hasBigRedNose; not equal ("ho")})
164      }
165
166      verify(mockClown, times(2)).hasBigRedNose
167    }
168  }
169
170  describe("Matcher expressions to the right of or") {
171    describe("(A plain-old matcher)") {
172      it("should not short-circuit if left matcher does match") {
173
174        val mockClown = mock[Clown]
175
176        "hi" should (have length (2) or { mockClown.hasBigRedNose; have length (2) })
177
178        verify(mockClown, times(1)).hasBigRedNose
179      }
180    }
181
182    describe("(have length N syntax)") {
183      it("should not short-circuit if left matcher does match") {
184
185        val mockClown = mock[Clown]
186
187        "hi" should (have length (2) or have length {mockClown.hasBigRedNose; 2})
188
189        verify(mockClown, times(1)).hasBigRedNose
190
191        "hi" should (have length (2) or {mockClown.hasBigRedNose; have length 2})
192
193        verify(mockClown, times(2)).hasBigRedNose
194      }
195    }
196
197    describe("(not have length N syntax)") {
198      it("should not short-circuit if left matcher does match") {
199
200        val mockClown = mock[Clown]
201
202        "hi" should (have length (2) or not have length {mockClown.hasBigRedNose; 1})
203
204        verify(mockClown, times(1)).hasBigRedNose
205
206        "hi" should (have length (2) or not {mockClown.hasBigRedNose; have length (1)})
207
208        verify(mockClown, times(2)).hasBigRedNose
209
210        "hi" should (have length (2) or {mockClown.hasBigRedNose; not have length (1)})
211
212        verify(mockClown, times(3)).hasBigRedNose
213      }
214    }
215
216    describe("(have size N syntax)") {
217      it("should not short-circuit if left matcher does match") {
218
219        val mockClown = mock[Clown]
220
221        Array(1, 2) should (have size (2) or have size {mockClown.hasBigRedNose; 2})
222
223        verify(mockClown, times(1)).hasBigRedNose
224
225        Array(1, 2) should (have size (2) or {mockClown.hasBigRedNose; have size 2})
226
227        verify(mockClown, times(2)).hasBigRedNose
228      }
229    }
230
231    describe("(not have size N syntax)") {
232      it("should not short-circuit if left matcher does match") {
233
234        val mockClown = mock[Clown]
235
236        Array(1, 2) should (have size (2) or not have size {mockClown.hasBigRedNose; 1})
237
238        verify(mockClown, times(1)).hasBigRedNose
239
240        Array(1, 2) should (have size (2) or not {mockClown.hasBigRedNose; have size (1)})
241
242        verify(mockClown, times(2)).hasBigRedNose
243
244        Array(1, 2) should (have size (2) or {mockClown.hasBigRedNose; not have size (1)})
245
246        verify(mockClown, times(3)).hasBigRedNose
247      }
248    }
249
250    describe("(equal N syntax)") {
251      it("should not short-circuit if left matcher does match") {
252
253        val mockClown = mock[Clown]
254
255        "hi" should (equal ("hi") or equal {mockClown.hasBigRedNose; "ho"})
256
257        verify(mockClown, times(1)).hasBigRedNose
258
259        "hi" should (equal ("hi") or {mockClown.hasBigRedNose; equal ("ho")})
260
261        verify(mockClown, times(2)).hasBigRedNose
262      }
263    }
264
265    describe("(be >/</>=/<= syntax)") {
266      it("should not short-circuit if left matcher does match for <") {
267
268        val mockClown = mock[Clown]
269
270        5 should (be < (7) or be < {mockClown.hasBigRedNose; 3})
271
272        verify(mockClown, times(1)).hasBigRedNose
273
274        5 should (be < (7) or be < {mockClown.hasBigRedNose; 3})
275
276        verify(mockClown, times(2)).hasBigRedNose
277      }
278      it("should not short-circuit if left matcher does match for >") {
279
280        val mockClown = mock[Clown]
281
282        5 should (be > (3) or be > {mockClown.hasBigRedNose; 3})
283
284        verify(mockClown, times(1)).hasBigRedNose
285
286        5 should (be > (3) or be > {mockClown.hasBigRedNose; 3})
287
288        verify(mockClown, times(2)).hasBigRedNose
289      }
290    }
291
292    describe("(not equal N syntax)") {
293      it("should not short-circuit if left matcher does match for <") {
294
295        val mockClown = mock[Clown]
296
297        5 should (be < (3) or not be < {mockClown.hasBigRedNose; 3})
298
299        verify(mockClown, times(1)).hasBigRedNose
300
301        5 should (be < (3) or not be < {mockClown.hasBigRedNose; 3})
302
303        verify(mockClown, times(2)).hasBigRedNose
304      }
305      it("should not short-circuit if left matcher does match for >") {
306
307        val mockClown = mock[Clown]
308
309        5 should (be > (7) or not be > {mockClown.hasBigRedNose; 8})
310
311        verify(mockClown, times(1)).hasBigRedNose
312
313        5 should (be > (7) or not be > {mockClown.hasBigRedNose; 8})
314
315        verify(mockClown, times(2)).hasBigRedNose
316      }
317    }
318  }
319}
320