1/*
2 * Copyright 2001-2008 Artima, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.scalatest.matchers
17
18import org.scalatest._
19import org.scalatest.prop.Checkers
20import org.scalacheck._
21import Arbitrary._
22import Prop._
23
24class ShouldIncludeSubstringSpec extends Spec with ShouldMatchers with Checkers with ReturnsNormallyThrowsAssertion {
25
26describe("The include substring syntax") {
27
28    it("should do nothing if the string includes the specified substring") {
29
30      "1.78" should include ("1.7")
31      "21.7" should include ("1.7")
32      "21.78" should include ("1.7")
33      "1.7" should include ("1.7")
34      check((s: String, t: String, u: String) => returnsNormally(s + t + u should include (t)))
35    }
36
37    it("should do nothing if the string does not include the specified substring when used with not") {
38
39      "eight" should not { include ("1.7") }
40      "eight" should not include ("1.7")
41      check((s: String, t: String, u: String) => (s + u).indexOf(t) == -1 ==> returnsNormally(s + u should not (include (t))))
42      check((s: String, t: String, u: String) => (s + u).indexOf(t) == -1 ==> returnsNormally(s + u should not include (t)))
43    }
44
45    it("should do nothing if the string does not include the specified substring when used in a logical-and expression") {
46
47      "a1.7" should (include ("1.7") and (include ("1.7")))
48      "a1.7" should (include ("1.7") and (include ("1.7")))
49      "a1.7" should (include ("1.7") and (include ("1.7")))
50
51      "1.7b" should ((include ("1.7")) and (include ("1.7")))
52      "1.7b" should ((include ("1.7")) and (include ("1.7")))
53      "1.7b" should ((include ("1.7")) and (include ("1.7")))
54
55      "a1.7b" should (include ("1.7") and include ("1.7"))
56      "a1.7b" should (include ("1.7") and include ("1.7"))
57      "a1.7b" should (include ("1.7") and include ("1.7"))
58
59      "1.7" should (include ("1.7") and (include ("1.7")))
60      "1.7" should ((include ("1.7")) and (include ("1.7")))
61      "1.7" should (include ("1.7") and include ("1.7"))
62
63      check((s: String, t: String, u: String) => returnsNormally(s + t + u should (include (s) and include (t) and include (u))))
64    }
65
66    it("should do nothing if the string does not include the specified substring when used in a logical-or expression") {
67
68      "a1.7" should (include ("hello") or (include ("1.7")))
69      "a1.7" should (include ("hello") or (include ("1.7")))
70      "a1.7" should (include ("hello") or (include ("1.7")))
71
72      "1.7b" should ((include ("hello")) or (include ("1.7")))
73      "1.7b" should ((include ("hello")) or (include ("1.7")))
74      "1.7b" should ((include ("hello")) or (include ("1.7")))
75
76      "a1.7b" should (include ("hello") or include ("1.7"))
77      "a1.7b" should (include ("hello") or include ("1.7"))
78      "a1.7b" should (include ("hello") or include ("1.7"))
79
80      "1.7" should (include ("hello") or (include ("1.7")))
81      "1.7" should ((include ("hello")) or (include ("1.7")))
82      "1.7" should (include ("hello") or include ("1.7"))
83
84      check((s: String, t: String, u: String) => returnsNormally(s + t + u should (include ("hi") or include ("ho") or include (t))))
85    }
86
87    it("should do nothing if the string does not include the specified substring when used in a logical-and expression with not") {
88      "fred" should (not (include ("bob")) and not (include ("1.7")))
89      "fred" should ((not include ("bob")) and (not include ("1.7")))
90      "fred" should (not include ("bob") and not include ("1.7"))
91      check((s: String) => s.indexOf("bob") == -1 && s.indexOf("1.7") == -1 ==> returnsNormally(s should (not include ("bob") and not include ("1.7"))))
92    }
93
94    it("should do nothing if the string does not include the specified substring when used in a logical-or expression with not") {
95      "fred" should (not (include ("fred")) or not (include ("1.7")))
96      "fred" should ((not include ("fred")) or (not include ("1.7")))
97      "fred" should (not include ("fred") or not include ("1.7"))
98      check((s: String) => s.indexOf("a") == -1 || s.indexOf("b") == -1 ==> returnsNormally(s should (not include ("a") or not include ("b"))))
99    }
100
101    it("should throw TestFailedException if the string does not match the specified substring") {
102
103      val caught1 = intercept[TestFailedException] {
104        "1.7" should include ("1.78")
105      }
106      assert(caught1.getMessage === "\"1.7\" did not include substring \"1.78\"")
107
108      val caught2 = intercept[TestFailedException] {
109        "1.7" should include ("21.7")
110      }
111      assert(caught2.getMessage === "\"1.7\" did not include substring \"21.7\"")
112
113      val caught3 = intercept[TestFailedException] {
114        "-one.eight" should include ("1.7")
115      }
116      assert(caught3.getMessage === "\"-one.eight\" did not include substring \"1.7\"")
117
118      val caught6 = intercept[TestFailedException] {
119        "eight" should include ("1.7")
120      }
121      assert(caught6.getMessage === "\"eight\" did not include substring \"1.7\"")
122
123      val caught7 = intercept[TestFailedException] {
124        "one.eight" should include ("1.7")
125      }
126      assert(caught7.getMessage === "\"one.eight\" did not include substring \"1.7\"")
127
128      val caught8 = intercept[TestFailedException] {
129        "onedoteight" should include ("1.7")
130      }
131      assert(caught8.getMessage === "\"onedoteight\" did not include substring \"1.7\"")
132
133      val caught9 = intercept[TestFailedException] {
134        "***" should include ("1.7")
135      }
136      assert(caught9.getMessage === "\"***\" did not include substring \"1.7\"")
137
138      check((s: String) => s.indexOf("1.7") == -1 ==> throwsTestFailedException(s should include ("1.7")))
139    }
140
141    it("should throw TestFailedException if the string does matches the specified substring when used with not") {
142
143      val caught1 = intercept[TestFailedException] {
144        "1.7" should not { include ("1.7") }
145      }
146      assert(caught1.getMessage === "\"1.7\" included substring \"1.7\"")
147
148      val caught2 = intercept[TestFailedException] {
149        "1.7" should not { include ("1.7") }
150      }
151      assert(caught2.getMessage === "\"1.7\" included substring \"1.7\"")
152
153      val caught3 = intercept[TestFailedException] {
154        "-1.8" should not { include ("1.8") }
155      }
156      assert(caught3.getMessage === "\"-1.8\" included substring \"1.8\"")
157
158      val caught4 = intercept[TestFailedException] {
159        "8" should not { include ("8") }
160      }
161      assert(caught4.getMessage === "\"8\" included substring \"8\"")
162
163      val caught5 = intercept[TestFailedException] {
164        "1." should not { include (".") }
165      }
166      assert(caught5.getMessage === "\"1.\" included substring \".\"")
167
168      val caught11 = intercept[TestFailedException] {
169        "1.7" should not include ("1.7")
170      }
171      assert(caught11.getMessage === "\"1.7\" included substring \"1.7\"")
172
173      val caught13 = intercept[TestFailedException] {
174        "-1.8" should not include ("-")
175      }
176      assert(caught13.getMessage === "\"-1.8\" included substring \"-\"")
177
178      val caught14 = intercept[TestFailedException] {
179        "8" should not include ("")
180      }
181      assert(caught14.getMessage === "\"8\" included substring \"\"")
182
183      val caught15 = intercept[TestFailedException] {
184        "1." should not include ("1.")
185      }
186      assert(caught15.getMessage === "\"1.\" included substring \"1.\"")
187
188      val caught21 = intercept[TestFailedException] {
189        "a1.7" should not { include ("1.7") }
190      }
191      assert(caught21.getMessage === "\"a1.7\" included substring \"1.7\"")
192
193      val caught22 = intercept[TestFailedException] {
194        "1.7b" should not { include ("1.7") }
195      }
196      assert(caught22.getMessage === "\"1.7b\" included substring \"1.7\"")
197
198      val caught23 = intercept[TestFailedException] {
199        "a-1.8b" should not { include ("1.8") }
200      }
201      assert(caught23.getMessage === "\"a-1.8b\" included substring \"1.8\"")
202
203      // substring at the beginning
204      check((s: String) => s.length != 0 ==> throwsTestFailedException(s should not include (s.substring(0, 1))))
205      // substring at the end
206      check((s: String) => s.length != 0 ==> throwsTestFailedException(s should not include (s.substring(s.length - 1, s.length))))
207      // substring in the middle
208      check((s: String) => s.length > 1 ==> throwsTestFailedException(s should not include (s.substring(1, 2))))
209    }
210
211    it("should throw TestFailedException if the string includes the specified substring when used in a logical-and expression") {
212
213      val caught1 = intercept[TestFailedException] {
214        "1.7" should (include ("1.7") and (include ("1.8")))
215      }
216      assert(caught1.getMessage === "\"1.7\" included substring \"1.7\", but \"1.7\" did not include substring \"1.8\"")
217
218      val caught2 = intercept[TestFailedException] {
219        "1.7" should ((include ("1.7")) and (include ("1.8")))
220      }
221      assert(caught2.getMessage === "\"1.7\" included substring \"1.7\", but \"1.7\" did not include substring \"1.8\"")
222
223      val caught3 = intercept[TestFailedException] {
224        "1.7" should (include ("1.7") and include ("1.8"))
225      }
226      assert(caught3.getMessage === "\"1.7\" included substring \"1.7\", but \"1.7\" did not include substring \"1.8\"")
227
228      // Check to make sure the error message "short circuits" (i.e., just reports the left side's failure)
229      val caught4 = intercept[TestFailedException] {
230        "one.eight" should (include ("1.7") and (include ("1.8")))
231      }
232      assert(caught4.getMessage === "\"one.eight\" did not include substring \"1.7\"")
233
234      val caught5 = intercept[TestFailedException] {
235        "one.eight" should ((include ("1.7")) and (include ("1.8")))
236      }
237      assert(caught5.getMessage === "\"one.eight\" did not include substring \"1.7\"")
238
239      val caught6 = intercept[TestFailedException] {
240        "one.eight" should (include ("1.7") and include ("1.8"))
241      }
242      assert(caught6.getMessage === "\"one.eight\" did not include substring \"1.7\"")
243
244      check((s: String, t: String, u: String) => (s + u).indexOf(t) == -1 ==> throwsTestFailedException(s + u should (include (s) and include (t))))
245    }
246
247    it("should throw TestFailedException if the string includes the specified substring when used in a logical-or expression") {
248
249      val caught1 = intercept[TestFailedException] {
250        "one.seven" should (include ("1.7") or (include ("1.8")))
251      }
252      assert(caught1.getMessage === "\"one.seven\" did not include substring \"1.7\", and \"one.seven\" did not include substring \"1.8\"")
253
254      val caught2 = intercept[TestFailedException] {
255        "one.seven" should ((include ("1.7")) or (include ("1.8")))
256      }
257      assert(caught2.getMessage === "\"one.seven\" did not include substring \"1.7\", and \"one.seven\" did not include substring \"1.8\"")
258
259      val caught3 = intercept[TestFailedException] {
260        "one.seven" should (include ("1.7") or include ("1.8"))
261      }
262      assert(caught3.getMessage === "\"one.seven\" did not include substring \"1.7\", and \"one.seven\" did not include substring \"1.8\"")
263
264      check(
265        (s: String, t: String, u: String, v: String) => {
266          (t.length != 0 && v.length != 0 && (s + u).indexOf(t) == -1 && (s + u).indexOf(v) == -1) ==>
267            throwsTestFailedException(s + u should (include (t) or include (v)))
268        }
269      )
270    }
271
272    it("should throw TestFailedException if the string includes the specified substring when used in a logical-and expression used with not") {
273
274      val caught1 = intercept[TestFailedException] {
275        "1.7" should (not include ("1.8") and (not include ("1.7")))
276      }
277      assert(caught1.getMessage === "\"1.7\" did not include substring \"1.8\", but \"1.7\" included substring \"1.7\"")
278
279      val caught2 = intercept[TestFailedException] {
280        "1.7" should ((not include ("1.8")) and (not include ("1.7")))
281      }
282      assert(caught2.getMessage === "\"1.7\" did not include substring \"1.8\", but \"1.7\" included substring \"1.7\"")
283
284      val caught3 = intercept[TestFailedException] {
285        "1.7" should (not include ("1.8") and not include ("1.7"))
286      }
287      assert(caught3.getMessage === "\"1.7\" did not include substring \"1.8\", but \"1.7\" included substring \"1.7\"")
288
289      val caught4 = intercept[TestFailedException] {
290        "a1.7" should (not include ("1.8") and (not include ("1.7")))
291      }
292      assert(caught4.getMessage === "\"a1.7\" did not include substring \"1.8\", but \"a1.7\" included substring \"1.7\"")
293
294      val caught5 = intercept[TestFailedException] {
295        "1.7b" should ((not include ("1.8")) and (not include ("1.7")))
296      }
297      assert(caught5.getMessage === "\"1.7b\" did not include substring \"1.8\", but \"1.7b\" included substring \"1.7\"")
298
299      val caught6 = intercept[TestFailedException] {
300        "a1.7b" should (not include ("1.8") and not include ("1.7"))
301      }
302      assert(caught6.getMessage === "\"a1.7b\" did not include substring \"1.8\", but \"a1.7b\" included substring \"1.7\"")
303
304      check(
305        (s: String, t: String, u: String) =>
306          (s + t + u).indexOf("hi") == -1 ==>
307            throwsTestFailedException(s + t + u should (not include ("hi") and not include (t)))
308      )
309    }
310
311    it("should throw TestFailedException if the string includes the specified substring when used in a logical-or expression used with not") {
312
313      val caught1 = intercept[TestFailedException] {
314        "1.7" should (not include ("1.7") or (not include ("1.7")))
315      }
316      assert(caught1.getMessage === "\"1.7\" included substring \"1.7\", and \"1.7\" included substring \"1.7\"")
317
318      val caught2 = intercept[TestFailedException] {
319        "1.7" should ((not include ("1.7")) or (not include ("1.7")))
320      }
321      assert(caught2.getMessage === "\"1.7\" included substring \"1.7\", and \"1.7\" included substring \"1.7\"")
322
323      val caught3 = intercept[TestFailedException] {
324        "1.7" should (not include ("1.7") or not include ("1.7"))
325      }
326      assert(caught3.getMessage === "\"1.7\" included substring \"1.7\", and \"1.7\" included substring \"1.7\"")
327
328      val caught4 = intercept[TestFailedException] {
329        "1.7" should (not (include ("1.7")) or not (include ("1.7")))
330      }
331      assert(caught4.getMessage === "\"1.7\" included substring \"1.7\", and \"1.7\" included substring \"1.7\"")
332
333      val caught5 = intercept[TestFailedException] {
334        "a1.7" should (not include ("1.7") or (not include ("1.7")))
335      }
336      assert(caught5.getMessage === "\"a1.7\" included substring \"1.7\", and \"a1.7\" included substring \"1.7\"")
337
338      val caught6 = intercept[TestFailedException] {
339        "1.7b" should ((not include ("1.7")) or (not include ("1.7")))
340      }
341      assert(caught6.getMessage === "\"1.7b\" included substring \"1.7\", and \"1.7b\" included substring \"1.7\"")
342
343      val caught7 = intercept[TestFailedException] {
344        "a1.7b" should (not include ("1.7") or not include ("1.7"))
345      }
346      assert(caught7.getMessage === "\"a1.7b\" included substring \"1.7\", and \"a1.7b\" included substring \"1.7\"")
347
348      val caught8 = intercept[TestFailedException] {
349        "a1.7b" should (not (include ("1.7")) or not (include ("1.7")))
350      }
351      assert(caught8.getMessage === "\"a1.7b\" included substring \"1.7\", and \"a1.7b\" included substring \"1.7\"")
352
353      check(
354        (s: String, t: String, u: String) =>
355          throwsTestFailedException(s + t + u should (not include (s) or not include (t) or not include (u)))
356      )
357    }
358  }
359}
360
361