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._
23import Integer.MIN_VALUE
24
25class ShouldLengthSpec extends Spec with ShouldMatchers with Checkers with ReturnsNormallyThrowsAssertion {
26
27  // Checking for a specific length
28  describe("The 'have length (Int)' syntax") {
29
30    describe("on String") {
31
32      it("should do nothing if string length matches specified length") {
33        "hi" should have length (2)
34        check((s: String) => returnsNormally(s should have length (s.length)))
35      }
36
37      it("should do nothing if string length does not match and used with should not") {
38        "hi" should not { have length (3) }
39        "hi" should not have length (3)
40        check((s: String, i: Int) => i != s.length ==> returnsNormally(s should not { have length (i) }))
41        check((s: String, i: Int) => i != s.length ==> returnsNormally(s should not have length (i)))
42      }
43
44      it("should do nothing when string length matches and used in a logical-and expression") {
45        "hi" should (have length (2) and (have length (3 - 1)))
46        "hi" should (have length (2) and have length (3 - 1))
47      }
48
49      it("should do nothing when string length matches and used in a logical-or expression") {
50        "hi" should { have length (77) or (have length (3 - 1)) }
51        "hi" should (have length (77) or have length (3 - 1))
52      }
53
54      it("should do nothing when string length doesn't match and used in a logical-and expression with not") {
55        "hi" should (not (have length (5)) and not (have length (3)))
56        "hi" should { not have length (5) and (not have length (3)) }
57        "hi" should (not have length (5) and not have length (3))
58      }
59
60      it("should do nothing when string length doesn't match and used in a logical-or expression with not") {
61        "hi" should (not (have length (2)) or not (have length (3)))
62        "hi" should ((not have length (2)) or (not have length (3)))
63        "hi" should (not have length (2) or not have length (3))
64      }
65
66      it("should throw TestFailedException if string length does not match specified length") {
67        val caught1 = intercept[TestFailedException] {
68          "hi" should have length (3)
69        }
70        assert(caught1.getMessage === "\"hi\" did not have length 3")
71        check((s: String) => throwsTestFailedException(s should have length (s.length + 1)))
72      }
73
74      it("should throw TestFailedException with normal error message if specified length is negative") {
75        val caught1 = intercept[TestFailedException] {
76          "hi" should have length (-2)
77        }
78        assert(caught1.getMessage === "\"hi\" did not have length -2")
79        check((s: String) => throwsTestFailedException(s should have length (if (s.length == 0) -1 else -s.length)))
80      }
81
82      it("should throw an assertion error when string length doesn't match and used in a logical-and expression") {
83
84        val caught1 = intercept[TestFailedException] {
85          "hi" should { have length (5) and (have length (2 - 1)) }
86        }
87        assert(caught1.getMessage === "\"hi\" did not have length 5")
88
89        val caught2 = intercept[TestFailedException] {
90          "hi" should ((have length (5)) and (have length (2 - 1)))
91        }
92        assert(caught2.getMessage === "\"hi\" did not have length 5")
93
94        val caught3 = intercept[TestFailedException] {
95          "hi" should (have length (5) and have length (2 - 1))
96        }
97        assert(caught3.getMessage === "\"hi\" did not have length 5")
98      }
99
100      it("should throw an assertion error when string length doesn't match and used in a logical-or expression") {
101
102        val caught1 = intercept[TestFailedException] {
103          "hi" should { have length (55) or (have length (22)) }
104        }
105        assert(caught1.getMessage === "\"hi\" did not have length 55, and \"hi\" did not have length 22")
106
107        val caught2 = intercept[TestFailedException] {
108          "hi" should ((have length (55)) or (have length (22)))
109        }
110        assert(caught2.getMessage === "\"hi\" did not have length 55, and \"hi\" did not have length 22")
111
112        val caught3 = intercept[TestFailedException] {
113          "hi" should (have length (55) or have length (22))
114        }
115        assert(caught3.getMessage === "\"hi\" did not have length 55, and \"hi\" did not have length 22")
116      }
117
118      it("should throw an assertion error when string length matches and used in a logical-and expression with not") {
119
120        val caught1 = intercept[TestFailedException] {
121          "hi" should { not { have length (3) } and not { have length (2) }}
122        }
123        assert(caught1.getMessage === "\"hi\" did not have length 3, but \"hi\" had length 2")
124
125        val caught2 = intercept[TestFailedException] {
126          "hi" should { not have length (3) and (not have length (2)) }
127        }
128        assert(caught2.getMessage === "\"hi\" did not have length 3, but \"hi\" had length 2")
129
130        val caught3 = intercept[TestFailedException] {
131          "hi" should (not have length (3) and not have length (2))
132        }
133        assert(caught3.getMessage === "\"hi\" did not have length 3, but \"hi\" had length 2")
134      }
135
136      it("should throw an assertion error when string length matches and used in a logical-or expression with not") {
137
138        val caught1 = intercept[TestFailedException] {
139          "hi" should { not { have length (2) } or not { have length (2) }}
140        }
141        assert(caught1.getMessage === "\"hi\" had length 2, and \"hi\" had length 2")
142
143        val caught2 = intercept[TestFailedException] {
144          "hi" should { not have length (2) or (not have length (2)) }
145        }
146        assert(caught2.getMessage === "\"hi\" had length 2, and \"hi\" had length 2")
147
148        val caught3 = intercept[TestFailedException] {
149          "hi" should (not have length (2) or not have length (2))
150        }
151        assert(caught3.getMessage === "\"hi\" had length 2, and \"hi\" had length 2")
152      }
153
154      it("should give good error messages when more than two clauses are used with logical connectors") {
155
156        val caught1 = intercept[TestFailedException] {
157          "hi" should (not have length (1) and not have length (3) and not have length (2))
158        }
159        assert(caught1.getMessage === "\"hi\" did not have length 1, and \"hi\" did not have length 3, but \"hi\" had length 2")
160
161        val caught2 = intercept[TestFailedException] {
162          "hi" should (not have length (2) or not equal ("hi") or equal ("frog"))
163        }
164        assert(caught2.getMessage === "\"hi\" had length 2, and \"hi\" equaled \"hi\", and \"hi\" did not equal \"frog\"")
165      }
166    }
167
168    describe("on Array") {
169
170      it("should do nothing if array length matches specified length") {
171        Array(1, 2) should have length (2)
172        // check((arr: Array[Int]) => returnsNormally(arr should have length (arr.length)))
173      }
174
175      it("should do nothing if array length does not match and used with should not") {
176        Array(1, 2) should not { have length (3) }
177        Array(1, 2) should not have length (3)
178        // check((arr: Array[Int], i: Int) => i != arr.length ==> returnsNormally(arr should not { have length (i) }))
179        // check((arr: Array[Int], i: Int) => i != arr.length ==> returnsNormally(arr should not have length (i)))
180      }
181
182      it("should do nothing when array length matches and used in a logical-and expression") {
183        Array(1, 2) should { have length (2) and (have length (3 - 1)) }
184        Array(1, 2) should (have length (2) and have length (3 - 1))
185      }
186
187      it("should do nothing when array length matches and used in a logical-or expression") {
188        Array(1, 2) should { have length (77) or (have length (3 - 1)) }
189        Array(1, 2) should (have length (77) or have length (3 - 1))
190      }
191
192      it("should do nothing when array length doesn't match and used in a logical-and expression with not") {
193        Array(1, 2) should { not { have length (5) } and not { have length (3) }}
194        Array(1, 2) should { not have length (5) and (not have length (3)) }
195        Array(1, 2) should (not have length (5) and not have length (3))
196      }
197
198      it("should do nothing when array length doesn't match and used in a logical-or expression with not") {
199        Array(1, 2) should { not { have length (2) } or not { have length (3) }}
200        Array(1, 2) should { not have length (2) or (not have length (3)) }
201        Array(1, 2) should (not have length (5) and not have length (3))
202      }
203
204      it("should throw TestFailedException if array length does not match specified length") {
205        val caught1 = intercept[TestFailedException] {
206          Array(1, 2) should have length (3)
207        }
208        assert(caught1.getMessage.endsWith("Array(1, 2) did not have length 3"))
209        // check((arr: Array[String]) => throwsTestFailedException(arr should have length (arr.length + 1)))
210      }
211
212      it("should throw TestFailedException with normal error message if specified length is negative") {
213        val caught1 = intercept[TestFailedException] {
214          Array(1, 2) should have length (-2)
215        }
216        assert(caught1.getMessage.endsWith("Array(1, 2) did not have length -2"))
217        // check((arr: Array[Int]) => throwsTestFailedException(arr should have length (if (arr.length == 0) -1 else -arr.length)))
218      }
219
220      it("should throw an assertion error when array length doesn't match and used in a logical-and expression") {
221
222        val caught1 = intercept[TestFailedException] {
223          Array(1, 2) should { have length (5) and (have length (2 - 1)) }
224        }
225        assert(caught1.getMessage === "Array(1, 2) did not have length 5")
226
227        val caught2 = intercept[TestFailedException] {
228          Array(1, 2) should ((have length (5)) and (have length (2 - 1)))
229        }
230        assert(caught2.getMessage === "Array(1, 2) did not have length 5")
231
232        val caught3 = intercept[TestFailedException] {
233          Array(1, 2) should (have length (5) and have length (2 - 1))
234        }
235        assert(caught3.getMessage === "Array(1, 2) did not have length 5")
236      }
237
238      it("should throw an assertion error when array length doesn't match and used in a logical-or expression") {
239
240        val caught1 = intercept[TestFailedException] {
241          Array(1, 2) should { have length (55) or (have length (22)) }
242        }
243        assert(caught1.getMessage === "Array(1, 2) did not have length 55, and Array(1, 2) did not have length 22")
244
245        val caught2 = intercept[TestFailedException] {
246          Array(1, 2) should ((have length (55)) or (have length (22)))
247        }
248        assert(caught2.getMessage === "Array(1, 2) did not have length 55, and Array(1, 2) did not have length 22")
249
250        val caught3 = intercept[TestFailedException] {
251          Array(1, 2) should (have length (55) or have length (22))
252        }
253        assert(caught3.getMessage === "Array(1, 2) did not have length 55, and Array(1, 2) did not have length 22")
254      }
255
256      it("should throw an assertion error when array length matches and used in a logical-and expression with not") {
257
258        val caught1 = intercept[TestFailedException] {
259          Array(1, 2) should { not { have length (3) } and not { have length (2) }}
260        }
261        assert(caught1.getMessage === "Array(1, 2) did not have length 3, but Array(1, 2) had length 2")
262
263        val caught2 = intercept[TestFailedException] {
264          Array(1, 2) should { not have length (3) and (not have length (2)) }
265        }
266        assert(caught2.getMessage === "Array(1, 2) did not have length 3, but Array(1, 2) had length 2")
267
268        val caught3 = intercept[TestFailedException] {
269          Array(1, 2) should (not have length (3) and not have length (2))
270        }
271        assert(caught3.getMessage === "Array(1, 2) did not have length 3, but Array(1, 2) had length 2")
272      }
273
274      it("should throw an assertion error when array length matches and used in a logical-or expression with not") {
275
276        val caught1 = intercept[TestFailedException] {
277          Array(1, 2) should { not { have length (2) } or not { have length (2) }}
278        }
279        assert(caught1.getMessage === "Array(1, 2) had length 2, and Array(1, 2) had length 2")
280
281        val caught2 = intercept[TestFailedException] {
282          Array(1, 2) should { not have length (2) or (not have length (2)) }
283        }
284        assert(caught2.getMessage === "Array(1, 2) had length 2, and Array(1, 2) had length 2")
285
286        val caught3 = intercept[TestFailedException] {
287          Array(1, 2) should (not have length (2) or not have length (2))
288        }
289        assert(caught3.getMessage === "Array(1, 2) had length 2, and Array(1, 2) had length 2")
290      }
291    }
292
293    describe("on scala.List") {
294
295      it("should do nothing if list length matches specified length") {
296        List(1, 2) should have length (2)
297        check((lst: List[Int]) => returnsNormally(lst should have length (lst.length)))
298      }
299
300      it("should do nothing if list length does not match and used with should not") {
301        List(1, 2) should not { have length (3) }
302        List(1, 2) should not have length (3)
303        check((lst: List[Int], i: Int) => i != lst.length ==> returnsNormally(lst should not { have length (i) }))
304        check((lst: List[Int], i: Int) => i != lst.length ==> returnsNormally(lst should not have length (i)))
305      }
306
307      it("should do nothing when list length matches and used in a logical-and expression") {
308        List(1, 2) should { have length (2) and (have length (3 - 1)) }
309        List(1, 2) should (have length (2) and have length (3 - 1))
310      }
311
312      it("should do nothing when list length matches and used in a logical-or expression") {
313        List(1, 2) should { have length (77) or (have length (3 - 1)) }
314        List(1, 2) should (have length (77) or have length (3 - 1))
315      }
316
317      it("should do nothing when list length doesn't match and used in a logical-and expression with not") {
318        List(1, 2) should { not { have length (5) } and not { have length (3) }}
319        List(1, 2) should { not have length (5) and (not have length (3)) }
320      }
321
322      it("should do nothing when list length doesn't match and used in a logical-or expression with not") {
323        List(1, 2) should { not { have length (2) } or not { have length (3) }}
324        List(1, 2) should { not have length (2) or (not have length (3)) }
325        List(1, 2) should (not have length (5) and not have length (3))
326      }
327
328      it("should throw TestFailedException if list length does not match specified length") {
329        val caught1 = intercept[TestFailedException] {
330          List(1, 2) should have length (3)
331        }
332        assert(caught1.getMessage === "List(1, 2) did not have length 3")
333        check((lst: List[String]) => throwsTestFailedException(lst should have length (lst.length + 1)))
334      }
335
336      it("should throw TestFailedException with normal error message if specified length is negative") {
337        val caught1 = intercept[TestFailedException] {
338          List(1, 2) should have length (-2)
339        }
340        assert(caught1.getMessage === "List(1, 2) did not have length -2")
341        check((lst: List[Int]) => throwsTestFailedException(lst should have length (if (lst.length == 0) -1 else -lst.length)))
342      }
343
344      it("should throw an assertion error when list length doesn't match and used in a logical-and expression") {
345
346        val caught1 = intercept[TestFailedException] {
347          List(1, 2) should { have length (5) and (have length (2 - 1)) }
348        }
349        assert(caught1.getMessage === "List(1, 2) did not have length 5")
350
351        val caught2 = intercept[TestFailedException] {
352          List(1, 2) should ((have length (5)) and (have length (2 - 1)))
353        }
354        assert(caught2.getMessage === "List(1, 2) did not have length 5")
355
356        val caught3 = intercept[TestFailedException] {
357          List(1, 2) should (have length (5) and have length (2 - 1))
358        }
359        assert(caught3.getMessage === "List(1, 2) did not have length 5")
360      }
361
362      it("should throw an assertion error when list length doesn't match and used in a logical-or expression") {
363
364        val caught1 = intercept[TestFailedException] {
365          List(1, 2) should { have length (55) or (have length (22)) }
366        }
367        assert(caught1.getMessage === "List(1, 2) did not have length 55, and List(1, 2) did not have length 22")
368
369        val caught2 = intercept[TestFailedException] {
370          List(1, 2) should ((have length (55)) or (have length (22)))
371        }
372        assert(caught2.getMessage === "List(1, 2) did not have length 55, and List(1, 2) did not have length 22")
373
374        val caught3 = intercept[TestFailedException] {
375          List(1, 2) should (have length (55) or have length (22))
376        }
377        assert(caught3.getMessage === "List(1, 2) did not have length 55, and List(1, 2) did not have length 22")
378      }
379
380      it("should throw an assertion error when list length matches and used in a logical-and expression with not") {
381
382        val caught1 = intercept[TestFailedException] {
383          List(1, 2) should { not { have length (3) } and not { have length (2) }}
384        }
385        assert(caught1.getMessage === "List(1, 2) did not have length 3, but List(1, 2) had length 2")
386
387        val caught2 = intercept[TestFailedException] {
388          List(1, 2) should { not have length (3) and (not have length (2)) }
389        }
390        assert(caught2.getMessage === "List(1, 2) did not have length 3, but List(1, 2) had length 2")
391
392        val caught3 = intercept[TestFailedException] {
393          List(1, 2) should (not have length (3) and not have length (2))
394        }
395        assert(caught3.getMessage === "List(1, 2) did not have length 3, but List(1, 2) had length 2")
396      }
397
398      it("should throw an assertion error when list length matches and used in a logical-or expression with not") {
399
400        val caught1 = intercept[TestFailedException] {
401          List(1, 2) should { not { have length (2) } or not { have length (2) }}
402        }
403        assert(caught1.getMessage === "List(1, 2) had length 2, and List(1, 2) had length 2")
404
405        val caught2 = intercept[TestFailedException] {
406          List(1, 2) should { not have length (2) or (not have length (2)) }
407        }
408        assert(caught2.getMessage === "List(1, 2) had length 2, and List(1, 2) had length 2")
409
410        val caught3 = intercept[TestFailedException] {
411          List(1, 2) should (not have length (2) or not have length (2))
412        }
413        assert(caught3.getMessage === "List(1, 2) had length 2, and List(1, 2) had length 2")
414      }
415    }
416
417    describe("on java.List") {
418
419      val javaList: java.util.List[Int] = new java.util.ArrayList
420      javaList.add(1)
421      javaList.add(2)
422
423      it("should do nothing if list length matches specified length") {
424        javaList should have length (2)
425        // check((lst: java.util.List[Int]) => returnsNormally(lst should have length (lst.length)))
426      }
427
428      it("should do nothing if list length does not match and used with should not") {
429        javaList should not { have length (3) }
430        javaList should not have length (3)
431        // check((lst: List[Int], i: Int) => i != lst.length ==> returnsNormally(lst should not { have length (i) }))
432      }
433
434      it("should do nothing when list length matches and used in a logical-and expression") {
435        javaList should { have length (2) and (have length (3 - 1)) }
436        javaList should (have length (2) and have length (3 - 1))
437      }
438
439      it("should do nothing when list length matches and used in a logical-or expression") {
440        javaList should { have length (77) or (have length (3 - 1)) }
441        javaList should (have length (77) or have length (3 - 1))
442      }
443
444      it("should do nothing when list length doesn't match and used in a logical-and expression with not") {
445        javaList should { not { have length (5) } and not { have length (3) }}
446        javaList should (not have length (5) and not have length (3))
447      }
448
449      it("should do nothing when list length doesn't match and used in a logical-or expression with not") {
450        javaList should { not { have length (2) } or not { have length (3) }}
451        javaList should (not have length (2) or not have length (3))
452      }
453
454      it("should throw TestFailedException if list length does not match specified length") {
455        val caught1 = intercept[TestFailedException] {
456          javaList should have length (3)
457        }
458        assert(caught1.getMessage === "[1, 2] did not have length 3")
459        // check((lst: List[String]) => throwsTestFailedException(lst should have length (lst.length + 1)))
460      }
461
462      it("should throw TestFailedException with normal error message if specified length is negative") {
463        val caught1 = intercept[TestFailedException] {
464          javaList should have length (-2)
465        }
466        assert(caught1.getMessage === "[1, 2] did not have length -2")
467        // check((lst: List[Int]) => throwsTestFailedException(lst should have length (if (lst.length == 0) -1 else -lst.length)))
468      }
469
470      it("should throw an assertion error when list length doesn't match and used in a logical-and expression") {
471
472        val caught1 = intercept[TestFailedException] {
473          javaList should { have length (5) and (have length (2 - 1)) }
474        }
475        assert(caught1.getMessage === "[1, 2] did not have length 5")
476
477        val caught2 = intercept[TestFailedException] {
478          javaList should ((have length (5)) and (have length (2 - 1)))
479        }
480        assert(caught2.getMessage === "[1, 2] did not have length 5")
481
482        val caught3 = intercept[TestFailedException] {
483          javaList should (have length (5) and have length (2 - 1))
484        }
485        assert(caught3.getMessage === "[1, 2] did not have length 5")
486      }
487
488      it("should throw an assertion error when list length doesn't match and used in a logical-or expression") {
489
490        val caught1 = intercept[TestFailedException] {
491          javaList should { have length (55) or (have length (22)) }
492        }
493        assert(caught1.getMessage === "[1, 2] did not have length 55, and [1, 2] did not have length 22")
494
495        val caught2 = intercept[TestFailedException] {
496          javaList should ((have length (55)) or (have length (22)))
497        }
498        assert(caught2.getMessage === "[1, 2] did not have length 55, and [1, 2] did not have length 22")
499
500        val caught3 = intercept[TestFailedException] {
501          javaList should (have length (55) or have length (22))
502        }
503        assert(caught3.getMessage === "[1, 2] did not have length 55, and [1, 2] did not have length 22")
504      }
505
506      it("should throw an assertion error when list length matches and used in a logical-and expression with not") {
507
508        val caught1 = intercept[TestFailedException] {
509          javaList should { not { have length (3) } and not { have length (2) }}
510        }
511        assert(caught1.getMessage === "[1, 2] did not have length 3, but [1, 2] had length 2")
512
513        val caught2 = intercept[TestFailedException] {
514          javaList should { not have length (3) and (not have length (2)) }
515        }
516        assert(caught2.getMessage === "[1, 2] did not have length 3, but [1, 2] had length 2")
517
518        val caught3 = intercept[TestFailedException] {
519          javaList should (not have length (3) and not have length (2))
520        }
521        assert(caught3.getMessage === "[1, 2] did not have length 3, but [1, 2] had length 2")
522      }
523
524      it("should throw an assertion error when list length matches and used in a logical-or expression with not") {
525
526        val caught1 = intercept[TestFailedException] {
527          javaList should { not { have length (2) } or not { have length (2) }}
528        }
529        assert(caught1.getMessage === "[1, 2] had length 2, and [1, 2] had length 2")
530
531        val caught2 = intercept[TestFailedException] {
532          javaList should { not have length (2) or (not have length (2)) }
533        }
534        assert(caught2.getMessage === "[1, 2] had length 2, and [1, 2] had length 2")
535
536        val caught3 = intercept[TestFailedException] {
537          javaList should (not have length (2) or not have length (2))
538        }
539        assert(caught3.getMessage === "[1, 2] had length 2, and [1, 2] had length 2")
540      }
541    }
542
543    // I repeat these with copy and paste, becuase I need to test that each static structural type works, and
544    // that makes it hard to pass them to a common "behaves like" method
545    describe("on an arbitrary object that has an empty-paren Int length method") {
546
547      class Lengthy(len: Int) {
548        def length(): Int = len
549        override def toString = "lengthy"
550      }
551      val obj = new Lengthy(2)
552
553      it("should do nothing if object length matches specified length") {
554        obj should have length (2)
555        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
556      }
557
558      it("should do nothing if object length does not match and used with should not") {
559        obj should not { have length (3) }
560        obj should not have length (3)
561        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
562        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
563      }
564
565      it("should do nothing when object length matches and used in a logical-and expression") {
566        obj should { have length (2) and (have length (3 - 1)) }
567        obj should (have length (2) and have length (3 - 1))
568      }
569
570      it("should do nothing when object length matches and used in a logical-or expression") {
571        obj should { have length (77) or (have length (3 - 1)) }
572        obj should (have length (77) or have length (3 - 1))
573      }
574
575      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
576        obj should { not { have length (5) } and not { have length (3) }}
577        obj should (not have length (5) and not have length (3))
578      }
579
580      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
581        obj should { not { have length (2) } or not { have length (3) }}
582        obj should (not have length (2) or not have length (3))
583      }
584
585      it("should throw TestFailedException if object length does not match specified length") {
586        val caught1 = intercept[TestFailedException] {
587          obj should have length (3)
588        }
589        assert(caught1.getMessage === "lengthy did not have length 3")
590        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
591      }
592
593      it("should throw TestFailedException with normal error message if specified length is negative") {
594        val caught1 = intercept[TestFailedException] {
595          obj should have length (-2)
596        }
597        assert(caught1.getMessage === "lengthy did not have length -2")
598        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
599      }
600
601      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
602
603        val caught1 = intercept[TestFailedException] {
604          obj should { have length (5) and (have length (2 - 1)) }
605        }
606        assert(caught1.getMessage === "lengthy did not have length 5")
607
608        val caught2 = intercept[TestFailedException] {
609          obj should ((have length (5)) and (have length (2 - 1)))
610        }
611        assert(caught2.getMessage === "lengthy did not have length 5")
612
613        val caught3 = intercept[TestFailedException] {
614          obj should (have length (5) and have length (2 - 1))
615        }
616        assert(caught3.getMessage === "lengthy did not have length 5")
617      }
618
619      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
620
621        val caught1 = intercept[TestFailedException] {
622          obj should { have length (55) or (have length (22)) }
623        }
624        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
625
626        val caught2 = intercept[TestFailedException] {
627          obj should ((have length (55)) or (have length (22)))
628        }
629        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
630
631        val caught3 = intercept[TestFailedException] {
632          obj should (have length (55) or have length (22))
633        }
634        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
635      }
636
637      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
638
639        val caught1 = intercept[TestFailedException] {
640          obj should { not { have length (3) } and not { have length (2) }}
641        }
642        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
643
644        val caught2 = intercept[TestFailedException] {
645          obj should { { not have length (3) } and { not have length (2) }}
646        }
647        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
648
649        val caught3 = intercept[TestFailedException] {
650          obj should (not have length (3) and not have length (2))
651        }
652        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
653      }
654
655      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
656
657        val caught1 = intercept[TestFailedException] {
658          obj should { not { have length (2) } or not { have length (2) }}
659        }
660        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
661
662        val caught2 = intercept[TestFailedException] {
663          obj should { { not have length (2) } or { not have length (2) }}
664        }
665        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
666
667        val caught3 = intercept[TestFailedException] {
668          obj should (not have length (2) or not have length (2))
669        }
670        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
671      }
672    }
673
674    describe("on an arbitrary object that has a parameterless Int length method") {
675
676      class Lengthy(len: Int) {
677        def length: Int = len  // The only difference between the previous is the structure of this member
678        override def toString = "lengthy"
679      }
680      val obj = new Lengthy(2)
681
682      it("should do nothing if object length matches specified length") {
683        obj should have length (2)
684        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
685      }
686
687      it("should do nothing if object length does not match and used with should not") {
688        obj should not { have length (3) }
689        obj should not have length (3)
690        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
691        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
692      }
693
694      it("should do nothing when object length matches and used in a logical-and expression") {
695        obj should { have length (2) and (have length (3 - 1)) }
696        obj should (have length (2) and have length (3 - 1))
697      }
698
699      it("should do nothing when object length matches and used in a logical-or expression") {
700        obj should { have length (77) or (have length (3 - 1)) }
701        obj should (have length (77) or have length (3 - 1))
702      }
703
704      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
705        obj should { not { have length (5) } and not { have length (3) }}
706        obj should (not have length (5) and not have length (3))
707      }
708
709      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
710        obj should { not { have length (2) } or not { have length (3) }}
711        obj should (not have length (2) or not have length (3))
712      }
713
714      it("should throw TestFailedException if object length does not match specified length") {
715        val caught1 = intercept[TestFailedException] {
716          obj should have length (3)
717        }
718        assert(caught1.getMessage === "lengthy did not have length 3")
719        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
720      }
721
722      it("should throw TestFailedException with normal error message if specified length is negative") {
723        val caught1 = intercept[TestFailedException] {
724          obj should have length (-2)
725        }
726        assert(caught1.getMessage === "lengthy did not have length -2")
727        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
728      }
729
730      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
731
732        val caught1 = intercept[TestFailedException] {
733          obj should { have length (5) and (have length (2 - 1)) }
734        }
735        assert(caught1.getMessage === "lengthy did not have length 5")
736
737        val caught2 = intercept[TestFailedException] {
738          obj should ((have length (5)) and (have length (2 - 1)))
739        }
740        assert(caught2.getMessage === "lengthy did not have length 5")
741
742        val caught3 = intercept[TestFailedException] {
743          obj should (have length (5) and have length (2 - 1))
744        }
745        assert(caught3.getMessage === "lengthy did not have length 5")
746      }
747
748      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
749
750        val caught1 = intercept[TestFailedException] {
751          obj should { have length (55) or (have length (22)) }
752        }
753        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
754
755        val caught2 = intercept[TestFailedException] {
756          obj should ((have length (55)) or (have length (22)))
757        }
758        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
759
760        val caught3 = intercept[TestFailedException] {
761          obj should (have length (55) or have length (22))
762        }
763        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
764      }
765
766      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
767
768        val caught1 = intercept[TestFailedException] {
769          obj should { not { have length (3) } and not { have length (2) }}
770        }
771        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
772
773        val caught2 = intercept[TestFailedException] {
774          obj should { { not have length (3) } and { not have length (2) }}
775        }
776        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
777
778        val caught3 = intercept[TestFailedException] {
779          obj should (not have length (3) and not have length (2))
780        }
781        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
782      }
783
784      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
785
786        val caught1 = intercept[TestFailedException] {
787          obj should { not { have length (2) } or not { have length (2) }}
788        }
789        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
790
791        val caught2 = intercept[TestFailedException] {
792          obj should { { not have length (2) } or { not have length (2) }}
793        }
794        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
795
796        val caught3 = intercept[TestFailedException] {
797          obj should (not have length (2) or not have length (2))
798        }
799        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
800      }
801    }
802
803    describe("on an arbitrary object that has a Int length field") {
804
805      class Lengthy(len: Int) {
806        val length: Int = len // The only difference between the previous is the structure of this member
807        override def toString = "lengthy"
808      }
809      val obj = new Lengthy(2)
810
811      it("should do nothing if object length matches specified length") {
812        obj should have length (2)
813        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
814      }
815
816      it("should do nothing if object length does not match and used with should not") {
817        obj should not { have length (3) }
818        obj should not have length (3)
819        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
820        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
821      }
822
823      it("should do nothing when object length matches and used in a logical-and expression") {
824        obj should { have length (2) and (have length (3 - 1)) }
825        obj should (have length (2) and have length (3 - 1))
826      }
827
828      it("should do nothing when object length matches and used in a logical-or expression") {
829        obj should { have length (77) or (have length (3 - 1)) }
830        obj should (have length (77) or have length (3 - 1))
831      }
832
833      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
834        obj should { not { have length (5) } and not { have length (3) }}
835        obj should (not have length (5) and not have length (3))
836      }
837
838      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
839        obj should { not { have length (2) } or not { have length (3) }}
840        obj should (not have length (2) or not have length (3))
841      }
842
843      it("should throw TestFailedException if object length does not match specified length") {
844        val caught1 = intercept[TestFailedException] {
845          obj should have length (3)
846        }
847        assert(caught1.getMessage === "lengthy did not have length 3")
848        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
849      }
850
851      it("should throw TestFailedException with normal error message if specified length is negative") {
852        val caught1 = intercept[TestFailedException] {
853          obj should have length (-2)
854        }
855        assert(caught1.getMessage === "lengthy did not have length -2")
856        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
857      }
858
859      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
860
861        val caught1 = intercept[TestFailedException] {
862          obj should { have length (5) and (have length (2 - 1)) }
863        }
864        assert(caught1.getMessage === "lengthy did not have length 5")
865
866        val caught2 = intercept[TestFailedException] {
867          obj should ((have length (5)) and (have length (2 - 1)))
868        }
869        assert(caught2.getMessage === "lengthy did not have length 5")
870
871        val caught3 = intercept[TestFailedException] {
872          obj should (have length (5) and have length (2 - 1))
873        }
874        assert(caught3.getMessage === "lengthy did not have length 5")
875      }
876
877      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
878
879        val caught1 = intercept[TestFailedException] {
880          obj should { have length (55) or (have length (22)) }
881        }
882        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
883
884        val caught2 = intercept[TestFailedException] {
885          obj should ((have length (55)) or (have length (22)))
886        }
887        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
888
889        val caught3 = intercept[TestFailedException] {
890          obj should (have length (55) or have length (22))
891        }
892        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
893      }
894
895      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
896
897        val caught1 = intercept[TestFailedException] {
898          obj should { not { have length (3) } and not { have length (2) }}
899        }
900        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
901
902        val caught2 = intercept[TestFailedException] {
903          obj should { { not have length (3) } and { not have length (2) }}
904        }
905        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
906
907        val caught3 = intercept[TestFailedException] {
908          obj should (not have length (3) and not have length (2))
909        }
910        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
911      }
912
913      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
914
915        val caught1 = intercept[TestFailedException] {
916          obj should { not { have length (2) } or not { have length (2) }}
917        }
918        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
919
920        val caught2 = intercept[TestFailedException] {
921          obj should { { not have length (2) } or { not have length (2) }}
922        }
923        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
924
925        val caught3 = intercept[TestFailedException] {
926          obj should (not have length (2) or not have length (2))
927        }
928        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
929      }
930    }
931
932    describe("on an arbitrary object that has an empty-paren Int getLength method") {
933
934      class Lengthy(len: Int) {
935        def getLength(): Int = len  // The only difference between the previous is the structure of this member
936        override def toString = "lengthy"
937      }
938      val obj = new Lengthy(2)
939
940      it("should do nothing if object length matches specified length") {
941        obj should have length (2)
942        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
943      }
944
945      it("should do nothing if object length does not match and used with should not") {
946        obj should not { have length (3) }
947        obj should not have length (3)
948        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
949        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
950      }
951
952      it("should do nothing when object length matches and used in a logical-and expression") {
953        obj should { have length (2) and (have length (3 - 1)) }
954        obj should (have length (2) and have length (3 - 1))
955      }
956
957      it("should do nothing when object length matches and used in a logical-or expression") {
958        obj should { have length (77) or (have length (3 - 1)) }
959        obj should (have length (77) or have length (3 - 1))
960      }
961
962      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
963        obj should { not { have length (5) } and not { have length (3) }}
964        obj should (not have length (5) and not have length (3))
965      }
966
967      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
968        obj should { not { have length (2) } or not { have length (3) }}
969        obj should (not have length (2) or not have length (3))
970      }
971
972      it("should throw TestFailedException if object length does not match specified length") {
973        val caught1 = intercept[TestFailedException] {
974          obj should have length (3)
975        }
976        assert(caught1.getMessage === "lengthy did not have length 3")
977        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
978      }
979
980      it("should throw TestFailedException with normal error message if specified length is negative") {
981        val caught1 = intercept[TestFailedException] {
982          obj should have length (-2)
983        }
984        assert(caught1.getMessage === "lengthy did not have length -2")
985        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
986      }
987
988      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
989
990        val caught1 = intercept[TestFailedException] {
991          obj should { have length (5) and (have length (2 - 1)) }
992        }
993        assert(caught1.getMessage === "lengthy did not have length 5")
994
995        val caught2 = intercept[TestFailedException] {
996          obj should ((have length (5)) and (have length (2 - 1)))
997        }
998        assert(caught2.getMessage === "lengthy did not have length 5")
999
1000        val caught3 = intercept[TestFailedException] {
1001          obj should (have length (5) and have length (2 - 1))
1002        }
1003        assert(caught3.getMessage === "lengthy did not have length 5")
1004      }
1005
1006      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1007
1008        val caught1 = intercept[TestFailedException] {
1009          obj should { have length (55) or (have length (22)) }
1010        }
1011        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1012
1013        val caught2 = intercept[TestFailedException] {
1014          obj should ((have length (55)) or (have length (22)))
1015        }
1016        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1017
1018        val caught3 = intercept[TestFailedException] {
1019          obj should (have length (55) or have length (22))
1020        }
1021        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1022      }
1023
1024      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1025
1026        val caught1 = intercept[TestFailedException] {
1027          obj should { not { have length (3) } and not { have length (2) }}
1028        }
1029        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1030
1031        val caught2 = intercept[TestFailedException] {
1032          obj should { { not have length (3) } and { not have length (2) }}
1033        }
1034        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1035
1036        val caught3 = intercept[TestFailedException] {
1037          obj should (not have length (3) and not have length (2))
1038        }
1039        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1040      }
1041
1042      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1043
1044        val caught1 = intercept[TestFailedException] {
1045          obj should { not { have length (2) } or not { have length (2) }}
1046        }
1047        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1048
1049        val caught2 = intercept[TestFailedException] {
1050          obj should { { not have length (2) } or { not have length (2) }}
1051        }
1052        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1053
1054        val caught3 = intercept[TestFailedException] {
1055          obj should (not have length (2) or not have length (2))
1056        }
1057        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1058      }
1059    }
1060
1061    describe("on an arbitrary object that has a parameterless Int getLength method") {
1062
1063      class Lengthy(len: Int) {
1064        def getLength: Int = len  // The only difference between the previous is the structure of this member
1065        override def toString = "lengthy"
1066      }
1067      val obj = new Lengthy(2)
1068
1069      it("should do nothing if object length matches specified length") {
1070        obj should have length (2)
1071        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
1072      }
1073
1074      it("should do nothing if object length does not match and used with should not") {
1075        obj should not { have length (3) }
1076        obj should not have length (3)
1077        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1078        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1079      }
1080
1081      it("should do nothing when object length matches and used in a logical-and expression") {
1082        obj should { have length (2) and (have length (3 - 1)) }
1083        obj should (have length (2) and have length (3 - 1))
1084      }
1085
1086      it("should do nothing when object length matches and used in a logical-or expression") {
1087        obj should { have length (77) or (have length (3 - 1)) }
1088        obj should (have length (77) or have length (3 - 1))
1089      }
1090
1091      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
1092        obj should { not { have length (5) } and not { have length (3) }}
1093        obj should (not have length (5) and not have length (3))
1094      }
1095
1096      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
1097        obj should { not { have length (2) } or not { have length (3) }}
1098        obj should (not have length (2) or not have length (3))
1099      }
1100
1101      it("should throw TestFailedException if object length does not match specified length") {
1102        val caught1 = intercept[TestFailedException] {
1103          obj should have length (3)
1104        }
1105        assert(caught1.getMessage === "lengthy did not have length 3")
1106        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
1107      }
1108
1109      it("should throw TestFailedException with normal error message if specified length is negative") {
1110        val caught1 = intercept[TestFailedException] {
1111          obj should have length (-2)
1112        }
1113        assert(caught1.getMessage === "lengthy did not have length -2")
1114        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
1115      }
1116
1117      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
1118
1119        val caught1 = intercept[TestFailedException] {
1120          obj should { have length (5) and (have length (2 - 1)) }
1121        }
1122        assert(caught1.getMessage === "lengthy did not have length 5")
1123
1124        val caught2 = intercept[TestFailedException] {
1125          obj should ((have length (5)) and (have length (2 - 1)))
1126        }
1127        assert(caught2.getMessage === "lengthy did not have length 5")
1128
1129        val caught3 = intercept[TestFailedException] {
1130          obj should (have length (5) and have length (2 - 1))
1131        }
1132        assert(caught3.getMessage === "lengthy did not have length 5")
1133      }
1134
1135      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1136
1137        val caught1 = intercept[TestFailedException] {
1138          obj should { have length (55) or (have length (22)) }
1139        }
1140        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1141
1142        val caught2 = intercept[TestFailedException] {
1143          obj should ((have length (55)) or (have length (22)))
1144        }
1145        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1146
1147        val caught3 = intercept[TestFailedException] {
1148          obj should (have length (55) or have length (22))
1149        }
1150        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1151      }
1152
1153      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1154
1155        val caught1 = intercept[TestFailedException] {
1156          obj should { not { have length (3) } and not { have length (2) }}
1157        }
1158        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1159
1160        val caught2 = intercept[TestFailedException] {
1161          obj should { { not have length (3) } and { not have length (2) }}
1162        }
1163        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1164
1165        val caught3 = intercept[TestFailedException] {
1166          obj should (not have length (3) and not have length (2))
1167        }
1168        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1169      }
1170
1171      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1172
1173        val caught1 = intercept[TestFailedException] {
1174          obj should { not { have length (2) } or not { have length (2) }}
1175        }
1176        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1177
1178        val caught2 = intercept[TestFailedException] {
1179          obj should { { not have length (2) } or { not have length (2) }}
1180        }
1181        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1182
1183        val caught3 = intercept[TestFailedException] {
1184          obj should (not have length (2) or not have length (2))
1185        }
1186        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1187      }
1188    }
1189
1190    describe("on an arbitrary object that has an Int getLength field") {
1191
1192      class Lengthy(len: Int) {
1193        val getLength: Int = len // The only difference between the previous is the structure of this member
1194        override def toString = "lengthy"
1195      }
1196      val obj = new Lengthy(2)
1197
1198      it("should do nothing if object length matches specified length") {
1199        obj should have length (2)
1200        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
1201      }
1202
1203      it("should do nothing if object length does not match and used with should not") {
1204        obj should not { have length (3) }
1205        obj should not have length (3)
1206        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1207        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1208      }
1209
1210      it("should do nothing when object length matches and used in a logical-and expression") {
1211        obj should { have length (2) and (have length (3 - 1)) }
1212        obj should (have length (2) and have length (3 - 1))
1213      }
1214
1215      it("should do nothing when object length matches and used in a logical-or expression") {
1216        obj should { have length (77) or (have length (3 - 1)) }
1217        obj should (have length (77) or have length (3 - 1))
1218      }
1219
1220      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
1221        obj should { not { have length (5) } and not { have length (3) }}
1222        obj should (not have length (5) and not have length (3))
1223      }
1224
1225      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
1226        obj should { not { have length (2) } or not { have length (3) }}
1227        obj should (not have length (2) or not have length (3))
1228      }
1229
1230      it("should throw TestFailedException if object length does not match specified length") {
1231        val caught1 = intercept[TestFailedException] {
1232          obj should have length (3)
1233        }
1234        assert(caught1.getMessage === "lengthy did not have length 3")
1235        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
1236      }
1237
1238      it("should throw TestFailedException with normal error message if specified length is negative") {
1239        val caught1 = intercept[TestFailedException] {
1240          obj should have length (-2)
1241        }
1242        assert(caught1.getMessage === "lengthy did not have length -2")
1243        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
1244      }
1245
1246      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
1247
1248        val caught1 = intercept[TestFailedException] {
1249          obj should { have length (5) and (have length (2 - 1)) }
1250        }
1251        assert(caught1.getMessage === "lengthy did not have length 5")
1252
1253        val caught2 = intercept[TestFailedException] {
1254          obj should ((have length (5)) and (have length (2 - 1)))
1255        }
1256        assert(caught2.getMessage === "lengthy did not have length 5")
1257
1258        val caught3 = intercept[TestFailedException] {
1259          obj should (have length (5) and have length (2 - 1))
1260        }
1261        assert(caught3.getMessage === "lengthy did not have length 5")
1262      }
1263
1264      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1265
1266        val caught1 = intercept[TestFailedException] {
1267          obj should { have length (55) or (have length (22)) }
1268        }
1269        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1270
1271        val caught2 = intercept[TestFailedException] {
1272          obj should ((have length (55)) or (have length (22)))
1273        }
1274        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1275
1276        val caught3 = intercept[TestFailedException] {
1277          obj should (have length (55) or have length (22))
1278        }
1279        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1280      }
1281
1282      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1283
1284        val caught1 = intercept[TestFailedException] {
1285          obj should { not { have length (3) } and not { have length (2) }}
1286        }
1287        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1288
1289        val caught2 = intercept[TestFailedException] {
1290          obj should { { not have length (3) } and { not have length (2) }}
1291        }
1292        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1293
1294        val caught3 = intercept[TestFailedException] {
1295          obj should (not have length (3) and not have length (2))
1296        }
1297        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1298      }
1299
1300      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1301
1302        val caught1 = intercept[TestFailedException] {
1303          obj should { not { have length (2) } or not { have length (2) }}
1304        }
1305        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1306
1307        val caught2 = intercept[TestFailedException] {
1308          obj should { { not have length (2) } or { not have length (2) }}
1309        }
1310        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1311
1312        val caught3 = intercept[TestFailedException] {
1313          obj should (not have length (2) or not have length (2))
1314        }
1315        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1316      }
1317    }
1318
1319    describe("on an arbitrary object that has an empty-paren Long length method") {
1320
1321      class Lengthy(len: Long) {
1322        def length(): Long = len
1323        override def toString = "lengthy"
1324      }
1325      val obj = new Lengthy(2)
1326
1327      it("should do nothing if object length matches specified length") {
1328        obj should have length (2)
1329        obj should have length (2L)
1330        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
1331        check((len: Long) => returnsNormally(new Lengthy(len) should have length (len)))
1332      }
1333
1334      it("should do nothing if object length does not match and used with should not") {
1335        obj should not { have length (3) }
1336        obj should not { have length (3L) }
1337        obj should not have length (3)
1338        obj should not have length (3L)
1339        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1340        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1341        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1342        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1343      }
1344
1345      it("should do nothing when object length matches and used in a logical-and expression") {
1346        obj should { have length (2) and (have length (3 - 1)) }
1347        obj should { have length (2L) and (have length (3 - 1)) }
1348      }
1349
1350      it("should do nothing when object length matches and used in a logical-or expression") {
1351        obj should { have length (77) or (have length (2L)) }
1352        obj should { have length (77L) or (have length (2)) }
1353      }
1354
1355      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
1356        obj should { not { have length (5) } and not { have length (3) }}
1357        obj should (not have length (5) and not have length (3))
1358      }
1359
1360      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
1361        obj should { not { have length (2) } or not { have length (3) }}
1362        obj should (not have length (2) or not have length (3))
1363      }
1364
1365      it("should throw TestFailedException if object length does not match specified length") {
1366        val caught1 = intercept[TestFailedException] {
1367          obj should have length (3)
1368        }
1369        assert(caught1.getMessage === "lengthy did not have length 3")
1370        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
1371      }
1372
1373      it("should throw TestFailedException with normal error message if specified length is negative") {
1374        val caught1 = intercept[TestFailedException] {
1375          obj should have length (-2)
1376        }
1377        assert(caught1.getMessage === "lengthy did not have length -2")
1378        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
1379      }
1380
1381      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
1382
1383        val caught1 = intercept[TestFailedException] {
1384          obj should { have length (5) and (have length (2 - 1)) }
1385        }
1386        assert(caught1.getMessage === "lengthy did not have length 5")
1387
1388        val caught2 = intercept[TestFailedException] {
1389          obj should ((have length (5)) and (have length (2 - 1)))
1390        }
1391        assert(caught2.getMessage === "lengthy did not have length 5")
1392
1393        val caught3 = intercept[TestFailedException] {
1394          obj should (have length (5) and have length (2 - 1))
1395        }
1396        assert(caught3.getMessage === "lengthy did not have length 5")
1397      }
1398
1399      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1400
1401        val caught1 = intercept[TestFailedException] {
1402          obj should { have length (55) or (have length (22)) }
1403        }
1404        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1405
1406        val caught2 = intercept[TestFailedException] {
1407          obj should ((have length (55)) or (have length (22)))
1408        }
1409        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1410
1411        val caught3 = intercept[TestFailedException] {
1412          obj should (have length (55) or have length (22))
1413        }
1414        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1415      }
1416
1417      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1418
1419        val caught1 = intercept[TestFailedException] {
1420          obj should { not { have length (3) } and not { have length (2) }}
1421        }
1422        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1423
1424        val caught2 = intercept[TestFailedException] {
1425          obj should { { not have length (3) } and { not have length (2) }}
1426        }
1427        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1428
1429        val caught3 = intercept[TestFailedException] {
1430          obj should (not have length (3) and not have length (2))
1431        }
1432        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1433      }
1434
1435      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1436
1437        val caught1 = intercept[TestFailedException] {
1438          obj should { not { have length (2) } or not { have length (2) }}
1439        }
1440        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1441
1442        val caught2 = intercept[TestFailedException] {
1443          obj should { { not have length (2) } or { not have length (2) }}
1444        }
1445        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1446
1447        val caught3 = intercept[TestFailedException] {
1448          obj should (not have length (2) or not have length (2))
1449        }
1450        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1451      }
1452    }
1453
1454    describe("on an arbitrary object that has a parameterless Long length method") {
1455
1456      class Lengthy(len: Long) {
1457        def length: Long = len  // The only difference between the previous is the structure of this member
1458        override def toString = "lengthy"
1459      }
1460      val obj = new Lengthy(2)
1461
1462      it("should do nothing if object length matches specified length") {
1463        obj should have length (2)
1464        obj should have length (2L)
1465        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
1466        check((len: Long) => returnsNormally(new Lengthy(len) should have length (len)))
1467      }
1468
1469      it("should do nothing if object length does not match and used with should not") {
1470        obj should not { have length (3) }
1471        obj should not { have length (3L) }
1472        obj should not have length (3)
1473        obj should not have length (3L)
1474        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1475        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1476        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1477        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1478      }
1479
1480      it("should do nothing when object length matches and used in a logical-and expression") {
1481        obj should { have length (2) and (have length (3 - 1)) }
1482        obj should (have length (2) and have length (3 - 1))
1483      }
1484
1485      it("should do nothing when object length matches and used in a logical-or expression") {
1486        obj should { have length (77) or (have length (3 - 1)) }
1487        obj should (have length (77) or have length (3 - 1))
1488      }
1489
1490      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
1491        obj should { not { have length (5) } and not { have length (3) }}
1492        obj should (not have length (5) and not have length (3))
1493      }
1494
1495      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
1496        obj should { not { have length (2) } or not { have length (3) }}
1497        obj should (not have length (2) or not have length (3))
1498      }
1499
1500      it("should throw TestFailedException if object length does not match specified length") {
1501        val caught1 = intercept[TestFailedException] {
1502          obj should have length (3)
1503        }
1504        assert(caught1.getMessage === "lengthy did not have length 3")
1505        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
1506      }
1507
1508      it("should throw TestFailedException with normal error message if specified length is negative") {
1509        val caught1 = intercept[TestFailedException] {
1510          obj should have length (-2)
1511        }
1512        assert(caught1.getMessage === "lengthy did not have length -2")
1513        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
1514      }
1515
1516      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
1517
1518        val caught1 = intercept[TestFailedException] {
1519          obj should { have length (5) and (have length (2 - 1)) }
1520        }
1521        assert(caught1.getMessage === "lengthy did not have length 5")
1522
1523        val caught2 = intercept[TestFailedException] {
1524          obj should ((have length (5)) and (have length (2 - 1)))
1525        }
1526        assert(caught2.getMessage === "lengthy did not have length 5")
1527
1528        val caught3 = intercept[TestFailedException] {
1529          obj should (have length (5) and have length (2 - 1))
1530        }
1531        assert(caught3.getMessage === "lengthy did not have length 5")
1532      }
1533
1534      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1535
1536        val caught1 = intercept[TestFailedException] {
1537          obj should { have length (55) or (have length (22)) }
1538        }
1539        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1540
1541        val caught2 = intercept[TestFailedException] {
1542          obj should ((have length (55)) or (have length (22)))
1543        }
1544        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1545
1546        val caught3 = intercept[TestFailedException] {
1547          obj should (have length (55) or have length (22))
1548        }
1549        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1550      }
1551
1552      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1553
1554        val caught1 = intercept[TestFailedException] {
1555          obj should { not { have length (3) } and not { have length (2) }}
1556        }
1557        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1558
1559        val caught2 = intercept[TestFailedException] {
1560          obj should { { not have length (3) } and { not have length (2) }}
1561        }
1562        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1563
1564        val caught3 = intercept[TestFailedException] {
1565          obj should (not have length (3) and not have length (2))
1566        }
1567        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1568      }
1569
1570      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1571
1572        val caught1 = intercept[TestFailedException] {
1573          obj should { not { have length (2) } or not { have length (2) }}
1574        }
1575        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1576
1577        val caught2 = intercept[TestFailedException] {
1578          obj should { { not have length (2) } or { not have length (2) }}
1579        }
1580        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1581
1582        val caught3 = intercept[TestFailedException] {
1583          obj should (not have length (2) or not have length (2))
1584        }
1585        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1586      }
1587    }
1588
1589    describe("on an arbitrary object that has a Long length field") {
1590
1591      class Lengthy(len: Long) {
1592        val length: Long = len // The only difference between the previous is the structure of this member
1593        override def toString = "lengthy"
1594      }
1595      val obj = new Lengthy(2)
1596
1597      it("should do nothing if object length matches specified length") {
1598        obj should have length (2)
1599        obj should have length (2L)
1600        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
1601        check((len: Long) => returnsNormally(new Lengthy(len) should have length (len)))
1602      }
1603
1604      it("should do nothing if object length does not match and used with should not") {
1605        obj should not { have length (3) }
1606        obj should not have length (3)
1607        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1608        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1609      }
1610
1611      it("should do nothing when object length matches and used in a logical-and expression") {
1612        obj should { have length (2) and (have length (3 - 1)) }
1613        obj should (have length (2) and have length (3 - 1))
1614      }
1615
1616      it("should do nothing when object length matches and used in a logical-or expression") {
1617        obj should { have length (77) or (have length (3 - 1)) }
1618        obj should (have length (77) or have length (3 - 1))
1619      }
1620
1621      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
1622        obj should { not { have length (5) } and not { have length (3) }}
1623        obj should (not have length (5) and not have length (3))
1624      }
1625
1626      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
1627        obj should { not { have length (2) } or not { have length (3) }}
1628        obj should (not have length (2) or not have length (3))
1629      }
1630
1631      it("should throw TestFailedException if object length does not match specified length") {
1632        val caught1 = intercept[TestFailedException] {
1633          obj should have length (3)
1634        }
1635        assert(caught1.getMessage === "lengthy did not have length 3")
1636        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
1637      }
1638
1639      it("should throw TestFailedException with normal error message if specified length is negative") {
1640        val caught1 = intercept[TestFailedException] {
1641          obj should have length (-2)
1642        }
1643        assert(caught1.getMessage === "lengthy did not have length -2")
1644        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
1645      }
1646
1647      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
1648
1649        val caught1 = intercept[TestFailedException] {
1650          obj should { have length (5) and (have length (2 - 1)) }
1651        }
1652        assert(caught1.getMessage === "lengthy did not have length 5")
1653
1654        val caught2 = intercept[TestFailedException] {
1655          obj should ((have length (5)) and (have length (2 - 1)))
1656        }
1657        assert(caught2.getMessage === "lengthy did not have length 5")
1658
1659        val caught3 = intercept[TestFailedException] {
1660          obj should (have length (5) and have length (2 - 1))
1661        }
1662        assert(caught3.getMessage === "lengthy did not have length 5")
1663      }
1664
1665      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1666
1667        val caught1 = intercept[TestFailedException] {
1668          obj should { have length (55) or (have length (22)) }
1669        }
1670        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1671
1672        val caught2 = intercept[TestFailedException] {
1673          obj should ((have length (55)) or (have length (22)))
1674        }
1675        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1676
1677        val caught3 = intercept[TestFailedException] {
1678          obj should (have length (55) or have length (22))
1679        }
1680        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1681      }
1682
1683      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1684
1685        val caught1 = intercept[TestFailedException] {
1686          obj should { not { have length (3) } and not { have length (2) }}
1687        }
1688        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1689
1690        val caught2 = intercept[TestFailedException] {
1691          obj should { { not have length (3) } and { not have length (2) }}
1692        }
1693        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1694
1695        val caught3 = intercept[TestFailedException] {
1696          obj should (not have length (3) and not have length (2))
1697        }
1698        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1699      }
1700
1701      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1702
1703        val caught1 = intercept[TestFailedException] {
1704          obj should { not { have length (2) } or not { have length (2) }}
1705        }
1706        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1707
1708        val caught2 = intercept[TestFailedException] {
1709          obj should { { not have length (2) } or { not have length (2) }}
1710        }
1711        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1712
1713        val caught3 = intercept[TestFailedException] {
1714          obj should (not have length (2) or not have length (2))
1715        }
1716        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1717      }
1718    }
1719
1720    describe("on an arbitrary object that has an empty-paren Long getLength method") {
1721
1722      class Lengthy(len: Long) {
1723        def getLength(): Long = len  // The only difference between the previous is the structure of this member
1724        override def toString = "lengthy"
1725      }
1726      val obj = new Lengthy(2)
1727
1728      it("should do nothing if object length matches specified length") {
1729        obj should have length (2)
1730        obj should have length (2L)
1731        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
1732        check((len: Long) => returnsNormally(new Lengthy(len) should have length (len)))
1733      }
1734
1735      it("should do nothing if object length does not match and used with should not") {
1736        obj should not { have length (3) }
1737        obj should not { have length (3L) }
1738        obj should not have length (3)
1739        obj should not have length (3L)
1740        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1741        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1742        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1743        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1744      }
1745
1746      it("should do nothing when object length matches and used in a logical-and expression") {
1747        obj should { have length (2) and (have length (3 - 1)) }
1748        obj should (have length (2) and have length (3 - 1))
1749      }
1750
1751      it("should do nothing when object length matches and used in a logical-or expression") {
1752        obj should { have length (77) or (have length (3 - 1)) }
1753        obj should (have length (77) or have length (3 - 1))
1754      }
1755
1756      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
1757        obj should { not { have length (5) } and not { have length (3) }}
1758        obj should (not have length (5) and not have length (3))
1759      }
1760
1761      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
1762        obj should { not { have length (2) } or not { have length (3) }}
1763        obj should (not have length (2) or not have length (3))
1764      }
1765
1766      it("should throw TestFailedException if object length does not match specified length") {
1767        val caught1 = intercept[TestFailedException] {
1768          obj should have length (3)
1769        }
1770        assert(caught1.getMessage === "lengthy did not have length 3")
1771        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
1772      }
1773
1774      it("should throw TestFailedException with normal error message if specified length is negative") {
1775        val caught1 = intercept[TestFailedException] {
1776          obj should have length (-2)
1777        }
1778        assert(caught1.getMessage === "lengthy did not have length -2")
1779        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
1780      }
1781
1782      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
1783
1784        val caught1 = intercept[TestFailedException] {
1785          obj should { have length (5) and (have length (2 - 1)) }
1786        }
1787        assert(caught1.getMessage === "lengthy did not have length 5")
1788
1789        val caught2 = intercept[TestFailedException] {
1790          obj should ((have length (5)) and (have length (2 - 1)))
1791        }
1792        assert(caught2.getMessage === "lengthy did not have length 5")
1793
1794        val caught3 = intercept[TestFailedException] {
1795          obj should (have length (5) and have length (2 - 1))
1796        }
1797        assert(caught3.getMessage === "lengthy did not have length 5")
1798      }
1799
1800      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1801
1802        val caught1 = intercept[TestFailedException] {
1803          obj should { have length (55) or (have length (22)) }
1804        }
1805        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1806
1807        val caught2 = intercept[TestFailedException] {
1808          obj should ((have length (55)) or (have length (22)))
1809        }
1810        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1811
1812        val caught3 = intercept[TestFailedException] {
1813          obj should (have length (55) or have length (22))
1814        }
1815        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1816      }
1817
1818      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1819
1820        val caught1 = intercept[TestFailedException] {
1821          obj should { not { have length (3) } and not { have length (2) }}
1822        }
1823        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1824
1825        val caught2 = intercept[TestFailedException] {
1826          obj should { { not have length (3) } and { not have length (2) }}
1827        }
1828        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1829
1830        val caught3 = intercept[TestFailedException] {
1831          obj should (not have length (3) and not have length (2))
1832        }
1833        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1834      }
1835
1836      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1837
1838        val caught1 = intercept[TestFailedException] {
1839          obj should { not { have length (2) } or not { have length (2) }}
1840        }
1841        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1842
1843        val caught2 = intercept[TestFailedException] {
1844          obj should { { not have length (2) } or { not have length (2) }}
1845        }
1846        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1847
1848        val caught3 = intercept[TestFailedException] {
1849          obj should (not have length (2) or not have length (2))
1850        }
1851        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1852      }
1853    }
1854
1855    describe("on an arbitrary object that has a parameterless Long getLength method") {
1856
1857      class Lengthy(len: Long) {
1858        def getLength: Long = len  // The only difference between the previous is the structure of this member
1859        override def toString = "lengthy"
1860      }
1861      val obj = new Lengthy(2)
1862
1863      it("should do nothing if object length matches specified length") {
1864        obj should have length (2)
1865        obj should have length (2L)
1866        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
1867        check((len: Long) => returnsNormally(new Lengthy(len) should have length (len)))
1868      }
1869
1870      it("should do nothing if object length does not match and used with should not") {
1871        obj should not { have length (3) }
1872        obj should not { have length (3L) }
1873        obj should not have length (3)
1874        obj should not have length (3L)
1875        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1876        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
1877        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1878        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
1879      }
1880
1881      it("should do nothing when object length matches and used in a logical-and expression") {
1882        obj should { have length (2) and (have length (3 - 1)) }
1883        obj should (have length (2) and have length (3 - 1))
1884      }
1885
1886      it("should do nothing when object length matches and used in a logical-or expression") {
1887        obj should { have length (77) or (have length (3 - 1)) }
1888        obj should (have length (77) or have length (3 - 1))
1889      }
1890
1891      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
1892        obj should { not { have length (5) } and not { have length (3) }}
1893        obj should (not have length (5) and not have length (3))
1894      }
1895
1896      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
1897        obj should { not { have length (2) } or not { have length (3) }}
1898        obj should (not have length (2) or not have length (3))
1899      }
1900
1901      it("should throw TestFailedException if object length does not match specified length") {
1902        val caught1 = intercept[TestFailedException] {
1903          obj should have length (3)
1904        }
1905        assert(caught1.getMessage === "lengthy did not have length 3")
1906        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
1907      }
1908
1909      it("should throw TestFailedException with normal error message if specified length is negative") {
1910        val caught1 = intercept[TestFailedException] {
1911          obj should have length (-2)
1912        }
1913        assert(caught1.getMessage === "lengthy did not have length -2")
1914        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
1915      }
1916
1917      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
1918
1919        val caught1 = intercept[TestFailedException] {
1920          obj should { have length (5) and (have length (2 - 1)) }
1921        }
1922        assert(caught1.getMessage === "lengthy did not have length 5")
1923
1924        val caught2 = intercept[TestFailedException] {
1925          obj should ((have length (5)) and (have length (2 - 1)))
1926        }
1927        assert(caught2.getMessage === "lengthy did not have length 5")
1928
1929        val caught3 = intercept[TestFailedException] {
1930          obj should (have length (5) and have length (2 - 1))
1931        }
1932        assert(caught3.getMessage === "lengthy did not have length 5")
1933      }
1934
1935      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
1936
1937        val caught1 = intercept[TestFailedException] {
1938          obj should { have length (55) or (have length (22)) }
1939        }
1940        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1941
1942        val caught2 = intercept[TestFailedException] {
1943          obj should ((have length (55)) or (have length (22)))
1944        }
1945        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1946
1947        val caught3 = intercept[TestFailedException] {
1948          obj should (have length (55) or have length (22))
1949        }
1950        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
1951      }
1952
1953      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
1954
1955        val caught1 = intercept[TestFailedException] {
1956          obj should { not { have length (3) } and not { have length (2) }}
1957        }
1958        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1959
1960        val caught2 = intercept[TestFailedException] {
1961          obj should { { not have length (3) } and { not have length (2) }}
1962        }
1963        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1964
1965        val caught3 = intercept[TestFailedException] {
1966          obj should (not have length (3) and not have length (2))
1967        }
1968        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
1969      }
1970
1971      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
1972
1973        val caught1 = intercept[TestFailedException] {
1974          obj should { not { have length (2) } or not { have length (2) }}
1975        }
1976        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
1977
1978        val caught2 = intercept[TestFailedException] {
1979          obj should { { not have length (2) } or { not have length (2) }}
1980        }
1981        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
1982
1983        val caught3 = intercept[TestFailedException] {
1984          obj should (not have length (2) or not have length (2))
1985        }
1986        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
1987      }
1988    }
1989
1990    describe("on an arbitrary object that has a Long getLength field") {
1991
1992      class Lengthy(len: Long) {
1993        val getLength: Long = len // The only difference between the previous is the structure of this member
1994        override def toString = "lengthy"
1995      }
1996      val obj = new Lengthy(2)
1997
1998      it("should do nothing if object length matches specified length") {
1999        obj should have length (2)
2000        obj should have length (2L)
2001        check((len: Int) => returnsNormally(new Lengthy(len) should have length (len)))
2002        check((len: Long) => returnsNormally(new Lengthy(len) should have length (len)))
2003      }
2004
2005      it("should do nothing if object length does not match and used with should not") {
2006        obj should not { have length (3) }
2007        obj should not { have length (3L) }
2008        obj should not have length (3)
2009        obj should not have length (3L)
2010        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
2011        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not { have length (wrongLen) }))
2012        check((len: Int, wrongLen: Int) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
2013        check((len: Long, wrongLen: Long) => len != wrongLen ==> returnsNormally(new Lengthy(len) should not have length (wrongLen)))
2014      }
2015
2016      it("should do nothing when object length matches and used in a logical-and expression") {
2017        obj should { have length (2) and (have length (3 - 1)) }
2018        obj should (have length (2) and have length (3 - 1))
2019      }
2020
2021      it("should do nothing when object length matches and used in a logical-or expression") {
2022        obj should { have length (77) or (have length (3 - 1)) }
2023        obj should (have length (77) or have length (3 - 1))
2024      }
2025
2026      it("should do nothing when object length doesn't match and used in a logical-and expression with not") {
2027        obj should { not { have length (5) } and not { have length (3) }}
2028        obj should (not have length (5) and not have length (3))
2029      }
2030
2031      it("should do nothing when object length doesn't match and used in a logical-or expression with not") {
2032        obj should { not { have length (2) } or not { have length (3) }}
2033        obj should (not have length (2) or not have length (3))
2034      }
2035
2036      it("should throw TestFailedException if object length does not match specified length") {
2037        val caught1 = intercept[TestFailedException] {
2038          obj should have length (3)
2039        }
2040        assert(caught1.getMessage === "lengthy did not have length 3")
2041        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (len + 1)))
2042      }
2043
2044      it("should throw TestFailedException with normal error message if specified length is negative") {
2045        val caught1 = intercept[TestFailedException] {
2046          obj should have length (-2)
2047        }
2048        assert(caught1.getMessage === "lengthy did not have length -2")
2049        check((len: Int) => throwsTestFailedException(new Lengthy(len) should have length (if ((len == 0) || (len == MIN_VALUE)) -1 else -len)))
2050      }
2051
2052      it("should throw an assertion error when object length doesn't match and used in a logical-and expression") {
2053
2054        val caught1 = intercept[TestFailedException] {
2055          obj should { have length (5) and (have length (2 - 1)) }
2056        }
2057        assert(caught1.getMessage === "lengthy did not have length 5")
2058
2059        val caught2 = intercept[TestFailedException] {
2060          obj should ((have length (5)) and (have length (2 - 1)))
2061        }
2062        assert(caught2.getMessage === "lengthy did not have length 5")
2063
2064        val caught3 = intercept[TestFailedException] {
2065          obj should (have length (5) and have length (2 - 1))
2066        }
2067        assert(caught3.getMessage === "lengthy did not have length 5")
2068      }
2069
2070      it("should throw an assertion error when object length doesn't match and used in a logical-or expression") {
2071
2072        val caught1 = intercept[TestFailedException] {
2073          obj should { have length (55) or (have length (22)) }
2074        }
2075        assert(caught1.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
2076
2077        val caught2 = intercept[TestFailedException] {
2078          obj should ((have length (55)) or (have length (22)))
2079        }
2080        assert(caught2.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
2081
2082        val caught3 = intercept[TestFailedException] {
2083          obj should (have length (55) or have length (22))
2084        }
2085        assert(caught3.getMessage === "lengthy did not have length 55, and lengthy did not have length 22")
2086      }
2087
2088      it("should throw an assertion error when object length matches and used in a logical-and expression with not") {
2089
2090        val caught1 = intercept[TestFailedException] {
2091          obj should { not { have length (3) } and not { have length (2) }}
2092        }
2093        assert(caught1.getMessage === "lengthy did not have length 3, but lengthy had length 2")
2094
2095        val caught2 = intercept[TestFailedException] {
2096          obj should { { not have length (3) } and { not have length (2) }}
2097        }
2098        assert(caught2.getMessage === "lengthy did not have length 3, but lengthy had length 2")
2099
2100        val caught3 = intercept[TestFailedException] {
2101          obj should (not have length (3) and not have length (2))
2102        }
2103        assert(caught3.getMessage === "lengthy did not have length 3, but lengthy had length 2")
2104      }
2105
2106      it("should throw an assertion error when object length matches and used in a logical-or expression with not") {
2107
2108        val caught1 = intercept[TestFailedException] {
2109          obj should { not { have length (2) } or not { have length (2) }}
2110        }
2111        assert(caught1.getMessage === "lengthy had length 2, and lengthy had length 2")
2112
2113        val caught2 = intercept[TestFailedException] {
2114          obj should { { not have length (2) } or { not have length (2) }}
2115        }
2116        assert(caught2.getMessage === "lengthy had length 2, and lengthy had length 2")
2117
2118        val caught3 = intercept[TestFailedException] {
2119          obj should (not have length (2) or not have length (2))
2120        }
2121        assert(caught3.getMessage === "lengthy had length 2, and lengthy had length 2")
2122      }
2123    }
2124
2125    it("should give an TestFailedException with an arbitrary object that has no length member in an and expression") {
2126      class HasNoLength {
2127        val lengthiness: Int = 2
2128      }
2129      val hasNoLength = new HasNoLength
2130      val caught1 = intercept[TestFailedException] {
2131        hasNoLength should { have length (2) and equal (hasNoLength) }
2132      }
2133      val expectedMessage = "have length (2) used with an object that had no public field or method named length or getLength"
2134      assert(caught1.getMessage === expectedMessage)
2135      val caught2 = intercept[TestFailedException] {
2136        hasNoLength should not { have length (2) and equal (hasNoLength) }
2137      }
2138      assert(caught2.getMessage === expectedMessage)
2139    }
2140
2141    it("should call the Scala-style method on an arbitrary object that has multiple members with a valid lengths structure") {
2142      class Lengthy(len: Int) {
2143        def getLength: Int = len + 1
2144        def length: Int = len
2145        override def toString = "lengthy"
2146      }
2147      val obj = new Lengthy(2)
2148      val lengthMatcher = have length (2)
2149      lengthMatcher.apply(obj)
2150
2151      class IntAndLong(intLen: Int, longLen: Long) {
2152        def getLength: Int = intLen
2153        def length: Long = longLen
2154        override def toString = "lengthy"
2155      }
2156      val obj2 = new IntAndLong(3, 2)
2157      val lengthMatcher2 = have length (2)
2158      lengthMatcher2.apply(obj)
2159    }
2160  }
2161}
2162