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.scalacheck._
21import Arbitrary._
22import Prop._
23
24class ShouldBeTripleEqualsSpec extends Spec with ShouldMatchers with Checkers with ReturnsNormallyThrowsAssertion {
25
26  // Checking for a specific size
27  describe("The 'be === (x)' syntax") {
28
29    describe("when used with Arrays") {
30      it("should compare arrays structurally") {
31        Array(1, 2) should be === Array(1, 2)
32        val a1 = Array(1, 2, 3)
33        val a2 = Array(1, 2, 3)
34        val a3 = Array(4, 5, 6)
35        a1 should not be theSameInstanceAs (a2)
36        a1 should be === a2
37        intercept[TestFailedException] {
38          a1 should be === a3
39        }
40      }
41      it("should compare arrays deeply") {
42        val a1 = Array(1, Array("a", "b"), 3)
43        val a2 = Array(1, Array("a", "b"), 3)
44        val a3 = Array(1, Array("c", "d"), 3)
45        a1 should not be theSameInstanceAs (a2)
46        a1 should be === a2
47        intercept[TestFailedException] {
48          a1 should be === a3
49        }
50      }
51    }
52
53    describe("when used with nulls") {
54      it("should not throw NullPointerException") {
55        val s: String = null
56        intercept[TestFailedException] {
57          s should be === Array(1, 2)
58        }
59        s should be === null
60        intercept[TestFailedException] {
61          "hi" should be === null
62        }
63      }
64    }
65
66    describe("on Int") {
67
68      it("should do nothing if the comparison holds true") {
69        check((i: Int) => returnsNormally(i should be === (i)))
70        check((i: Int) => returnsNormally(i should be === i))
71      }
72
73      it("should do nothing if the comparison fails and used with not") {
74
75        check((left: Int, right: Int) => left != right ==> returnsNormally(left should not be === (right)))
76        check((left: Int, right: Int) => left != right ==> returnsNormally(left should not (be === (right))))
77        check((left: Int, right: Int) => left != right ==> returnsNormally(left should not (be === right)))
78      }
79
80      it("should do nothing when comparison succeeds and used in a logical-and expression") {
81
82        check((i: Int) => returnsNormally(i should ((be === (i)) and (be === (i)))))
83        check((i: Int) => returnsNormally(i should (be === (i) and (be === i))))
84        check((i: Int) => returnsNormally(i should (be === i and be === (i))))
85        check((i: Int) => returnsNormally(i should (be === i and be === i)))
86      }
87
88      it("should do nothing when comparison succeeds and used in a logical-or expression") {
89
90        check((i: Int) => returnsNormally(i should ((be === (i)) or (be === (i)))))
91        check((i: Int) => returnsNormally(i should (be === (i) or (be === i))))
92        check((i: Int) => returnsNormally(i should (be === i or be === (i))))
93        check((i: Int) => returnsNormally(i should (be === i or be === i)))
94
95        check((i: Int) => returnsNormally(i should ((not equal (i)) or (be === (i)))))
96        check((i: Int) => returnsNormally(i should (not equal (i) or (be === i))))
97        check((i: Int) => returnsNormally(i should ((not equal i or be === (i)))))
98        check((i: Int) => returnsNormally(i should ((not equal i) or be === i)))
99      }
100
101      it("should do nothing when comparison fails and used in a logical-and expression with not") {
102
103        check((left: Int, right: Int) => left != right ==> returnsNormally(left should (not (be === (right)) and not (be === (right)))))
104        check((left: Int, right: Int) => left != right ==> returnsNormally(left should ((not be === (right)) and (not be === (right)))))
105        check((left: Int, right: Int) => left != right ==> returnsNormally(left should (not be === (right) and not be === (right))))
106      }
107
108      it("should do nothing when comparison fails and used in a logical-or expression with not") {
109
110        check((left: Int, right: Int) => left != right ==> returnsNormally(left should (not (be === (right)) or not (be === (right)))))
111        check((left: Int, right: Int) => left != right ==> returnsNormally(left should ((not be === (right)) or (not be === (right)))))
112        check((left: Int, right: Int) => left != right ==> returnsNormally(left should (not be === (right) or not be === (right))))
113      }
114
115      it("should throw TestFailedException if comparison does not succeed") {
116
117        val caught1 = intercept[TestFailedException] {
118          1 should be === (2)
119        }
120        assert(caught1.getMessage === "1 was not equal to 2")
121        check((left: Int, right: Int) => left != right ==> throwsTestFailedException(left should be === (right)))
122
123        val caught2 = intercept[TestFailedException] {
124          1 should be === 2
125        }
126        assert(caught2.getMessage === "1 was not equal to 2")
127        check((left: Int, right: Int) => left != right ==> throwsTestFailedException(left should be === right))
128      }
129
130      it("should throw TestFailedException if comparison succeeds but used with not") {
131
132        val caught1 = intercept[TestFailedException] {
133          1 should not be === (1)
134        }
135        assert(caught1.getMessage === "1 was equal to 1")
136        check((i: Int) => throwsTestFailedException(i should not be === (i)))
137      }
138
139      // Comparison with and
140      it("should throw TestFailedException when comparison doesn't succeed and used in a logical-and expression") {
141
142        val caught1 = intercept[TestFailedException] {
143          2 should { be === (2) and (be === (5)) }
144        }
145        assert(caught1.getMessage === "2 was equal to 2, but 2 was not equal to 5")
146
147        val caught2 = intercept[TestFailedException] {
148          2 should ((be === (2)) and (be === (5)))
149        }
150        assert(caught2.getMessage === "2 was equal to 2, but 2 was not equal to 5")
151
152        val caught3 = intercept[TestFailedException] {
153          2 should (be === (2) and be === (5))
154        }
155        assert(caught3.getMessage === "2 was equal to 2, but 2 was not equal to 5")
156
157        val caught4 = intercept[TestFailedException] {
158          2 should (be === 2 and be === 5)
159        }
160        assert(caught4.getMessage === "2 was equal to 2, but 2 was not equal to 5")
161
162        val caught5 = intercept[TestFailedException] {
163          2 should (be === 5 and be === 2)
164        }
165        assert(caught5.getMessage === "2 was not equal to 5")
166      }
167
168      // Comparison with or
169      it("should throw throw TestFailedException when comparison doesn't succeed and used in a logical-or expression") {
170
171
172        val caught1 = intercept[TestFailedException] {
173          2 should { be === (3) or (be === (5)) }
174        }
175        assert(caught1.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
176
177        val caught2 = intercept[TestFailedException] {
178          2 should ((be === (3)) or (be === (5)))
179        }
180        assert(caught2.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
181
182        val caught3 = intercept[TestFailedException] {
183          2 should (be === (3) or be === (5))
184        }
185        assert(caught3.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
186
187        val caught4 = intercept[TestFailedException] {
188          2 should (be === 3 or be === 5)
189        }
190        assert(caught4.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
191      }
192
193      // Comparison with and not
194      it("should throw throw TestFailedException when comparison doesn't succeed and used in a logical-and expression used with not") {
195
196        val caught1 = intercept[TestFailedException] {
197          5 should { not { be === (2) } and not { be === (5) }}
198        }
199        assert(caught1.getMessage === "5 was not equal to 2, but 5 was equal to 5")
200
201        val caught2 = intercept[TestFailedException] {
202          5 should ((not be === (2)) and (not be === (5)))
203        }
204        assert(caught2.getMessage === "5 was not equal to 2, but 5 was equal to 5")
205
206        val caught3 = intercept[TestFailedException] {
207          5 should (not be === (2) and not be === (5))
208        }
209        assert(caught3.getMessage === "5 was not equal to 2, but 5 was equal to 5")
210      }
211
212      // Comparison with or not
213      it("should throw throw TestFailedException when comparison doesn't succeed and used in a logical-or expression used with not") {
214
215        val caught1 = intercept[TestFailedException] {
216          5 should { not { be === (5) } or not { be === (5) }}
217        }
218        assert(caught1.getMessage === "5 was equal to 5, and 5 was equal to 5")
219
220        val caught2 = intercept[TestFailedException] {
221          5 should ((not be === (5)) or (not be === (5)))
222        }
223        assert(caught2.getMessage === "5 was equal to 5, and 5 was equal to 5")
224
225        val caught3 = intercept[TestFailedException] {
226          // 5 should ((not be === (5)).or(not).be(===(5)))
227          5 should (not be === (5) or not be === (5))
228        }
229        assert(caught3.getMessage === "5 was equal to 5, and 5 was equal to 5")
230      }
231    }
232
233    describe("on String") {
234
235      it("should do nothing if the comparison holds true") {
236        check((s: String) => returnsNormally(s should be === (s)))
237        check((s: String) => returnsNormally(s should be === s))
238      }
239
240      it("should do nothing if the comparison fails and used with not") {
241
242        check((left: String, right: String) => left != right ==> returnsNormally(left should not be === (right)))
243        check((left: String, right: String) => left != right ==> returnsNormally(left should not (be === (right))))
244        check((left: String, right: String) => left != right ==> returnsNormally(left should not (be === right)))
245      }
246
247      it("should do nothing when comparison succeeds and used in a logical-and expression") {
248
249        check((s: String) => returnsNormally(s should ((be === (s)) and (be === (s)))))
250        check((s: String) => returnsNormally(s should (be === (s) and (be === s))))
251        check((s: String) => returnsNormally(s should (be === s and be === (s))))
252        check((s: String) => returnsNormally(s should (be === s and be === s)))
253      }
254
255      it("should do nothing when comparison succeeds and used in a logical-or expression") {
256
257        check((s: String) => returnsNormally(s should ((be === (s)) or (be === (s)))))
258        check((s: String) => returnsNormally(s should (be === (s) or (be === s))))
259        check((s: String) => returnsNormally(s should (be === s or be === (s))))
260        check((s: String) => returnsNormally(s should (be === s or be === s)))
261
262        check((s: String) => returnsNormally(s should ((not equal (s)) or (be === (s)))))
263        check((s: String) => returnsNormally(s should (not equal (s) or (be === s))))
264        check((s: String) => returnsNormally(s should ((not equal s or be === (s)))))
265        check((s: String) => returnsNormally(s should ((not equal s) or be === s)))
266      }
267
268      it("should do nothing when comparison fails and used in a logical-and expression with not") {
269
270        check((left: String, right: String) => left != right ==> returnsNormally(left should (not (be === (right)) and not (be === (right)))))
271        check((left: String, right: String) => left != right ==> returnsNormally(left should ((not be === (right)) and (not be === (right)))))
272        check((left: String, right: String) => left != right ==> returnsNormally(left should (not be === (right) and not be === (right))))
273      }
274
275      it("should do nothing when comparison fails and used in a logical-or expression with not") {
276
277        check((left: String, right: String) => left != right ==> returnsNormally(left should (not (be === (right)) or not (be === (right)))))
278        check((left: String, right: String) => left != right ==> returnsNormally(left should ((not be === (right)) or (not be === (right)))))
279        check((left: String, right: String) => left != right ==> returnsNormally(left should (not be === (right) or not be === (right))))
280      }
281
282      it("should throw TestFailedException if comparison does not succeed") {
283
284        val caught1 = intercept[TestFailedException] {
285          1 should be === (2)
286        }
287        assert(caught1.getMessage === "1 was not equal to 2")
288        check((left: String, right: String) => left != right ==> throwsTestFailedException(left should be === (right)))
289
290        val caught2 = intercept[TestFailedException] {
291          1 should be === 2
292        }
293        assert(caught2.getMessage === "1 was not equal to 2")
294        check((left: String, right: String) => left != right ==> throwsTestFailedException(left should be === right))
295      }
296
297      it("should throw TestFailedException if comparison succeeds but used with not") {
298
299        val caught1 = intercept[TestFailedException] {
300          1 should not be === (1)
301        }
302        assert(caught1.getMessage === "1 was equal to 1")
303        check((s: String) => throwsTestFailedException(s should not be === (s)))
304      }
305
306      // Comparison with and
307      it("should throw TestFailedException when comparison doesn't succeed and used in a logical-and expression") {
308
309        val caught1 = intercept[TestFailedException] {
310          2 should { be === (2) and (be === (5)) }
311        }
312        assert(caught1.getMessage === "2 was equal to 2, but 2 was not equal to 5")
313
314        val caught2 = intercept[TestFailedException] {
315          2 should ((be === (2)) and (be === (5)))
316        }
317        assert(caught2.getMessage === "2 was equal to 2, but 2 was not equal to 5")
318
319        val caught3 = intercept[TestFailedException] {
320          2 should (be === (2) and be === (5))
321        }
322        assert(caught3.getMessage === "2 was equal to 2, but 2 was not equal to 5")
323
324        val caught4 = intercept[TestFailedException] {
325          2 should (be === 2 and be === 5)
326        }
327        assert(caught4.getMessage === "2 was equal to 2, but 2 was not equal to 5")
328
329        val caught5 = intercept[TestFailedException] {
330          2 should (be === 5 and be === 2)
331        }
332        assert(caught5.getMessage === "2 was not equal to 5")
333      }
334
335      // Comparison with or
336      it("should throw throw TestFailedException when comparison doesn't succeed and used in a logical-or expression") {
337
338
339        val caught1 = intercept[TestFailedException] {
340          2 should { be === (3) or (be === (5)) }
341        }
342        assert(caught1.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
343
344        val caught2 = intercept[TestFailedException] {
345          2 should ((be === (3)) or (be === (5)))
346        }
347        assert(caught2.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
348
349        val caught3 = intercept[TestFailedException] {
350          2 should (be === (3) or be === (5))
351        }
352        assert(caught3.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
353
354        val caught4 = intercept[TestFailedException] {
355          2 should (be === 3 or be === 5)
356        }
357        assert(caught4.getMessage === "2 was not equal to 3, and 2 was not equal to 5")
358      }
359
360      // Comparison with and not
361      it("should throw throw TestFailedException when comparison doesn't succeed and used in a logical-and expression used with not") {
362
363        val caught1 = intercept[TestFailedException] {
364          5 should { not { be === (2) } and not { be === (5) }}
365        }
366        assert(caught1.getMessage === "5 was not equal to 2, but 5 was equal to 5")
367
368        val caught2 = intercept[TestFailedException] {
369          5 should ((not be === (2)) and (not be === (5)))
370        }
371        assert(caught2.getMessage === "5 was not equal to 2, but 5 was equal to 5")
372
373        val caught3 = intercept[TestFailedException] {
374          5 should (not be === (2) and not be === (5))
375        }
376        assert(caught3.getMessage === "5 was not equal to 2, but 5 was equal to 5")
377      }
378
379      // Comparison with or not
380      it("should throw throw TestFailedException when comparison doesn't succeed and used in a logical-or expression used with not") {
381
382        val caught1 = intercept[TestFailedException] {
383          5 should { not { be === (5) } or not { be === (5) }}
384        }
385        assert(caught1.getMessage === "5 was equal to 5, and 5 was equal to 5")
386
387        val caught2 = intercept[TestFailedException] {
388          5 should ((not be === (5)) or (not be === (5)))
389        }
390        assert(caught2.getMessage === "5 was equal to 5, and 5 was equal to 5")
391
392        val caught3 = intercept[TestFailedException] {
393          // 5 should ((not be === (5)).or(not).be(===(5)))
394          5 should (not be === (5) or not be === (5))
395        }
396        assert(caught3.getMessage === "5 was equal to 5, and 5 was equal to 5")
397      }
398    }
399  }
400}
401