smbd_open_one_socket does not use the messaging_context variable so why pass it in?
[metze/samba/wip.git] / lib / testtools / testtools / tests / test_matchers.py
1 # Copyright (c) 2008-2011 testtools developers. See LICENSE for details.
2
3 """Tests for matchers."""
4
5 import doctest
6 import re
7 import os
8 import shutil
9 import sys
10 import tarfile
11 import tempfile
12
13 from testtools import (
14     Matcher, # check that Matcher is exposed at the top level for docs.
15     skipIf,
16     TestCase,
17     )
18 from testtools.compat import (
19     StringIO,
20     str_is_unicode,
21     text_repr,
22     _b,
23     _u,
24     )
25 from testtools.matchers import (
26     AfterPreprocessing,
27     AllMatch,
28     Annotate,
29     AnnotatedMismatch,
30     _BinaryMismatch,
31     Contains,
32     DirContains,
33     DirExists,
34     DocTestMatches,
35     DoesNotEndWith,
36     DoesNotStartWith,
37     EndsWith,
38     Equals,
39     FileContains,
40     FileExists,
41     HasPermissions,
42     KeysEqual,
43     Is,
44     IsInstance,
45     LessThan,
46     GreaterThan,
47     MatchesAny,
48     MatchesAll,
49     MatchesException,
50     MatchesListwise,
51     MatchesPredicate,
52     MatchesRegex,
53     MatchesSetwise,
54     MatchesStructure,
55     Mismatch,
56     MismatchDecorator,
57     MismatchError,
58     Not,
59     NotEquals,
60     PathExists,
61     Raises,
62     raises,
63     SamePath,
64     StartsWith,
65     TarballContains,
66     )
67 from testtools.tests.helpers import FullStackRunTest
68
69 # Silence pyflakes.
70 Matcher
71
72
73 class TestMismatch(TestCase):
74
75     run_tests_with = FullStackRunTest
76
77     def test_constructor_arguments(self):
78         mismatch = Mismatch("some description", {'detail': "things"})
79         self.assertEqual("some description", mismatch.describe())
80         self.assertEqual({'detail': "things"}, mismatch.get_details())
81
82     def test_constructor_no_arguments(self):
83         mismatch = Mismatch()
84         self.assertThat(mismatch.describe,
85             Raises(MatchesException(NotImplementedError)))
86         self.assertEqual({}, mismatch.get_details())
87
88
89 class TestMismatchError(TestCase):
90
91     def test_is_assertion_error(self):
92         # MismatchError is an AssertionError, so that most of the time, it
93         # looks like a test failure, rather than an error.
94         def raise_mismatch_error():
95             raise MismatchError(2, Equals(3), Equals(3).match(2))
96         self.assertRaises(AssertionError, raise_mismatch_error)
97
98     def test_default_description_is_mismatch(self):
99         mismatch = Equals(3).match(2)
100         e = MismatchError(2, Equals(3), mismatch)
101         self.assertEqual(mismatch.describe(), str(e))
102
103     def test_default_description_unicode(self):
104         matchee = _u('\xa7')
105         matcher = Equals(_u('a'))
106         mismatch = matcher.match(matchee)
107         e = MismatchError(matchee, matcher, mismatch)
108         self.assertEqual(mismatch.describe(), str(e))
109
110     def test_verbose_description(self):
111         matchee = 2
112         matcher = Equals(3)
113         mismatch = matcher.match(2)
114         e = MismatchError(matchee, matcher, mismatch, True)
115         expected = (
116             'Match failed. Matchee: %r\n'
117             'Matcher: %s\n'
118             'Difference: %s\n' % (
119                 matchee,
120                 matcher,
121                 matcher.match(matchee).describe(),
122                 ))
123         self.assertEqual(expected, str(e))
124
125     def test_verbose_unicode(self):
126         # When assertThat is given matchees or matchers that contain non-ASCII
127         # unicode strings, we can still provide a meaningful error.
128         matchee = _u('\xa7')
129         matcher = Equals(_u('a'))
130         mismatch = matcher.match(matchee)
131         expected = (
132             'Match failed. Matchee: %s\n'
133             'Matcher: %s\n'
134             'Difference: %s\n' % (
135                 text_repr(matchee),
136                 matcher,
137                 mismatch.describe(),
138                 ))
139         e = MismatchError(matchee, matcher, mismatch, True)
140         if str_is_unicode:
141             actual = str(e)
142         else:
143             actual = unicode(e)
144             # Using str() should still work, and return ascii only
145             self.assertEqual(
146                 expected.replace(matchee, matchee.encode("unicode-escape")),
147                 str(e).decode("ascii"))
148         self.assertEqual(expected, actual)
149
150
151 class Test_BinaryMismatch(TestCase):
152     """Mismatches from binary comparisons need useful describe output"""
153
154     _long_string = "This is a longish multiline non-ascii string\n\xa7"
155     _long_b = _b(_long_string)
156     _long_u = _u(_long_string)
157
158     def test_short_objects(self):
159         o1, o2 = object(), object()
160         mismatch = _BinaryMismatch(o1, "!~", o2)
161         self.assertEqual(mismatch.describe(), "%r !~ %r" % (o1, o2))
162
163     def test_short_mixed_strings(self):
164         b, u = _b("\xa7"), _u("\xa7")
165         mismatch = _BinaryMismatch(b, "!~", u)
166         self.assertEqual(mismatch.describe(), "%r !~ %r" % (b, u))
167
168     def test_long_bytes(self):
169         one_line_b = self._long_b.replace(_b("\n"), _b(" "))
170         mismatch = _BinaryMismatch(one_line_b, "!~", self._long_b)
171         self.assertEqual(mismatch.describe(),
172             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
173                 text_repr(one_line_b),
174                 text_repr(self._long_b, multiline=True)))
175
176     def test_long_unicode(self):
177         one_line_u = self._long_u.replace("\n", " ")
178         mismatch = _BinaryMismatch(one_line_u, "!~", self._long_u)
179         self.assertEqual(mismatch.describe(),
180             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
181                 text_repr(one_line_u),
182                 text_repr(self._long_u, multiline=True)))
183
184     def test_long_mixed_strings(self):
185         mismatch = _BinaryMismatch(self._long_b, "!~", self._long_u)
186         self.assertEqual(mismatch.describe(),
187             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
188                 text_repr(self._long_b, multiline=True),
189                 text_repr(self._long_u, multiline=True)))
190
191     def test_long_bytes_and_object(self):
192         obj = object()
193         mismatch = _BinaryMismatch(self._long_b, "!~", obj)
194         self.assertEqual(mismatch.describe(),
195             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
196                 text_repr(self._long_b, multiline=True),
197                 repr(obj)))
198
199     def test_long_unicode_and_object(self):
200         obj = object()
201         mismatch = _BinaryMismatch(self._long_u, "!~", obj)
202         self.assertEqual(mismatch.describe(),
203             "%s:\nreference = %s\nactual    = %s\n" % ("!~",
204                 text_repr(self._long_u, multiline=True),
205                 repr(obj)))
206
207
208 class TestMatchersInterface(object):
209
210     run_tests_with = FullStackRunTest
211
212     def test_matches_match(self):
213         matcher = self.matches_matcher
214         matches = self.matches_matches
215         mismatches = self.matches_mismatches
216         for candidate in matches:
217             self.assertEqual(None, matcher.match(candidate))
218         for candidate in mismatches:
219             mismatch = matcher.match(candidate)
220             self.assertNotEqual(None, mismatch)
221             self.assertNotEqual(None, getattr(mismatch, 'describe', None))
222
223     def test__str__(self):
224         # [(expected, object to __str__)].
225         examples = self.str_examples
226         for expected, matcher in examples:
227             self.assertThat(matcher, DocTestMatches(expected))
228
229     def test_describe_difference(self):
230         # [(expected, matchee, matcher), ...]
231         examples = self.describe_examples
232         for difference, matchee, matcher in examples:
233             mismatch = matcher.match(matchee)
234             self.assertEqual(difference, mismatch.describe())
235
236     def test_mismatch_details(self):
237         # The mismatch object must provide get_details, which must return a
238         # dictionary mapping names to Content objects.
239         examples = self.describe_examples
240         for difference, matchee, matcher in examples:
241             mismatch = matcher.match(matchee)
242             details = mismatch.get_details()
243             self.assertEqual(dict(details), details)
244
245
246 class TestDocTestMatchesInterface(TestCase, TestMatchersInterface):
247
248     matches_matcher = DocTestMatches("Ran 1 test in ...s", doctest.ELLIPSIS)
249     matches_matches = ["Ran 1 test in 0.000s", "Ran 1 test in 1.234s"]
250     matches_mismatches = ["Ran 1 tests in 0.000s", "Ran 2 test in 0.000s"]
251
252     str_examples = [("DocTestMatches('Ran 1 test in ...s\\n')",
253         DocTestMatches("Ran 1 test in ...s")),
254         ("DocTestMatches('foo\\n', flags=8)", DocTestMatches("foo", flags=8)),
255         ]
256
257     describe_examples = [('Expected:\n    Ran 1 tests in ...s\nGot:\n'
258         '    Ran 1 test in 0.123s\n', "Ran 1 test in 0.123s",
259         DocTestMatches("Ran 1 tests in ...s", doctest.ELLIPSIS))]
260
261
262 class TestDocTestMatchesInterfaceUnicode(TestCase, TestMatchersInterface):
263
264     matches_matcher = DocTestMatches(_u("\xa7..."), doctest.ELLIPSIS)
265     matches_matches = [_u("\xa7"), _u("\xa7 more\n")]
266     matches_mismatches = ["\\xa7", _u("more \xa7"), _u("\n\xa7")]
267
268     str_examples = [("DocTestMatches(%r)" % (_u("\xa7\n"),),
269         DocTestMatches(_u("\xa7"))),
270         ]
271
272     describe_examples = [(
273         _u("Expected:\n    \xa7\nGot:\n    a\n"),
274         "a",
275         DocTestMatches(_u("\xa7"), doctest.ELLIPSIS))]
276
277
278 class TestDocTestMatchesSpecific(TestCase):
279
280     run_tests_with = FullStackRunTest
281
282     def test___init__simple(self):
283         matcher = DocTestMatches("foo")
284         self.assertEqual("foo\n", matcher.want)
285
286     def test___init__flags(self):
287         matcher = DocTestMatches("bar\n", doctest.ELLIPSIS)
288         self.assertEqual("bar\n", matcher.want)
289         self.assertEqual(doctest.ELLIPSIS, matcher.flags)
290
291     def test_describe_non_ascii_bytes(self):
292         """Even with bytestrings, the mismatch should be coercible to unicode
293
294         DocTestMatches is intended for text, but the Python 2 str type also
295         permits arbitrary binary inputs. This is a slightly bogus thing to do,
296         and under Python 3 using bytes objects will reasonably raise an error.
297         """
298         header = _b("\x89PNG\r\n\x1a\n...")
299         if str_is_unicode:
300             self.assertRaises(TypeError,
301                 DocTestMatches, header, doctest.ELLIPSIS)
302             return
303         matcher = DocTestMatches(header, doctest.ELLIPSIS)
304         mismatch = matcher.match(_b("GIF89a\1\0\1\0\0\0\0;"))
305         # Must be treatable as unicode text, the exact output matters less
306         self.assertTrue(unicode(mismatch.describe()))
307
308
309 class TestEqualsInterface(TestCase, TestMatchersInterface):
310
311     matches_matcher = Equals(1)
312     matches_matches = [1]
313     matches_mismatches = [2]
314
315     str_examples = [("Equals(1)", Equals(1)), ("Equals('1')", Equals('1'))]
316
317     describe_examples = [("1 != 2", 2, Equals(1))]
318
319
320 class TestNotEqualsInterface(TestCase, TestMatchersInterface):
321
322     matches_matcher = NotEquals(1)
323     matches_matches = [2]
324     matches_mismatches = [1]
325
326     str_examples = [
327         ("NotEquals(1)", NotEquals(1)), ("NotEquals('1')", NotEquals('1'))]
328
329     describe_examples = [("1 == 1", 1, NotEquals(1))]
330
331
332 class TestIsInterface(TestCase, TestMatchersInterface):
333
334     foo = object()
335     bar = object()
336
337     matches_matcher = Is(foo)
338     matches_matches = [foo]
339     matches_mismatches = [bar, 1]
340
341     str_examples = [("Is(2)", Is(2))]
342
343     describe_examples = [("1 is not 2", 2, Is(1))]
344
345
346 class TestIsInstanceInterface(TestCase, TestMatchersInterface):
347
348     class Foo:pass
349
350     matches_matcher = IsInstance(Foo)
351     matches_matches = [Foo()]
352     matches_mismatches = [object(), 1, Foo]
353
354     str_examples = [
355             ("IsInstance(str)", IsInstance(str)),
356             ("IsInstance(str, int)", IsInstance(str, int)),
357             ]
358
359     describe_examples = [
360             ("'foo' is not an instance of int", 'foo', IsInstance(int)),
361             ("'foo' is not an instance of any of (int, type)", 'foo',
362              IsInstance(int, type)),
363             ]
364
365
366 class TestLessThanInterface(TestCase, TestMatchersInterface):
367
368     matches_matcher = LessThan(4)
369     matches_matches = [-5, 3]
370     matches_mismatches = [4, 5, 5000]
371
372     str_examples = [
373         ("LessThan(12)", LessThan(12)),
374         ]
375
376     describe_examples = [
377         ('4 is not > 5', 5, LessThan(4)),
378         ('4 is not > 4', 4, LessThan(4)),
379         ]
380
381
382 class TestGreaterThanInterface(TestCase, TestMatchersInterface):
383
384     matches_matcher = GreaterThan(4)
385     matches_matches = [5, 8]
386     matches_mismatches = [-2, 0, 4]
387
388     str_examples = [
389         ("GreaterThan(12)", GreaterThan(12)),
390         ]
391
392     describe_examples = [
393         ('5 is not < 4', 4, GreaterThan(5)),
394         ('4 is not < 4', 4, GreaterThan(4)),
395         ]
396
397
398 class TestContainsInterface(TestCase, TestMatchersInterface):
399
400     matches_matcher = Contains('foo')
401     matches_matches = ['foo', 'afoo', 'fooa']
402     matches_mismatches = ['f', 'fo', 'oo', 'faoo', 'foao']
403
404     str_examples = [
405         ("Contains(1)", Contains(1)),
406         ("Contains('foo')", Contains('foo')),
407         ]
408
409     describe_examples = [("1 not in 2", 2, Contains(1))]
410
411
412 def make_error(type, *args, **kwargs):
413     try:
414         raise type(*args, **kwargs)
415     except type:
416         return sys.exc_info()
417
418
419 class TestMatchesExceptionInstanceInterface(TestCase, TestMatchersInterface):
420
421     matches_matcher = MatchesException(ValueError("foo"))
422     error_foo = make_error(ValueError, 'foo')
423     error_bar = make_error(ValueError, 'bar')
424     error_base_foo = make_error(Exception, 'foo')
425     matches_matches = [error_foo]
426     matches_mismatches = [error_bar, error_base_foo]
427
428     str_examples = [
429         ("MatchesException(Exception('foo',))",
430          MatchesException(Exception('foo')))
431         ]
432     describe_examples = [
433         ("%r is not a %r" % (Exception, ValueError),
434          error_base_foo,
435          MatchesException(ValueError("foo"))),
436         ("ValueError('bar',) has different arguments to ValueError('foo',).",
437          error_bar,
438          MatchesException(ValueError("foo"))),
439         ]
440
441
442 class TestMatchesExceptionTypeInterface(TestCase, TestMatchersInterface):
443
444     matches_matcher = MatchesException(ValueError)
445     error_foo = make_error(ValueError, 'foo')
446     error_sub = make_error(UnicodeError, 'bar')
447     error_base_foo = make_error(Exception, 'foo')
448     matches_matches = [error_foo, error_sub]
449     matches_mismatches = [error_base_foo]
450
451     str_examples = [
452         ("MatchesException(%r)" % Exception,
453          MatchesException(Exception))
454         ]
455     describe_examples = [
456         ("%r is not a %r" % (Exception, ValueError),
457          error_base_foo,
458          MatchesException(ValueError)),
459         ]
460
461
462 class TestMatchesExceptionTypeReInterface(TestCase, TestMatchersInterface):
463
464     matches_matcher = MatchesException(ValueError, 'fo.')
465     error_foo = make_error(ValueError, 'foo')
466     error_sub = make_error(UnicodeError, 'foo')
467     error_bar = make_error(ValueError, 'bar')
468     matches_matches = [error_foo, error_sub]
469     matches_mismatches = [error_bar]
470
471     str_examples = [
472         ("MatchesException(%r)" % Exception,
473          MatchesException(Exception, 'fo.'))
474         ]
475     describe_examples = [
476         ("'bar' does not match /fo./",
477          error_bar, MatchesException(ValueError, "fo.")),
478         ]
479
480
481 class TestMatchesExceptionTypeMatcherInterface(TestCase, TestMatchersInterface):
482
483     matches_matcher = MatchesException(
484         ValueError, AfterPreprocessing(str, Equals('foo')))
485     error_foo = make_error(ValueError, 'foo')
486     error_sub = make_error(UnicodeError, 'foo')
487     error_bar = make_error(ValueError, 'bar')
488     matches_matches = [error_foo, error_sub]
489     matches_mismatches = [error_bar]
490
491     str_examples = [
492         ("MatchesException(%r)" % Exception,
493          MatchesException(Exception, Equals('foo')))
494         ]
495     describe_examples = [
496         ("5 != %r" % (error_bar[1],),
497          error_bar, MatchesException(ValueError, Equals(5))),
498         ]
499
500
501 class TestNotInterface(TestCase, TestMatchersInterface):
502
503     matches_matcher = Not(Equals(1))
504     matches_matches = [2]
505     matches_mismatches = [1]
506
507     str_examples = [
508         ("Not(Equals(1))", Not(Equals(1))),
509         ("Not(Equals('1'))", Not(Equals('1')))]
510
511     describe_examples = [('1 matches Equals(1)', 1, Not(Equals(1)))]
512
513
514 class TestMatchersAnyInterface(TestCase, TestMatchersInterface):
515
516     matches_matcher = MatchesAny(DocTestMatches("1"), DocTestMatches("2"))
517     matches_matches = ["1", "2"]
518     matches_mismatches = ["3"]
519
520     str_examples = [(
521         "MatchesAny(DocTestMatches('1\\n'), DocTestMatches('2\\n'))",
522         MatchesAny(DocTestMatches("1"), DocTestMatches("2"))),
523         ]
524
525     describe_examples = [("""Differences: [
526 Expected:
527     1
528 Got:
529     3
530
531 Expected:
532     2
533 Got:
534     3
535
536 ]""",
537         "3", MatchesAny(DocTestMatches("1"), DocTestMatches("2")))]
538
539
540 class TestMatchesAllInterface(TestCase, TestMatchersInterface):
541
542     matches_matcher = MatchesAll(NotEquals(1), NotEquals(2))
543     matches_matches = [3, 4]
544     matches_mismatches = [1, 2]
545
546     str_examples = [
547         ("MatchesAll(NotEquals(1), NotEquals(2))",
548          MatchesAll(NotEquals(1), NotEquals(2)))]
549
550     describe_examples = [
551         ("""Differences: [
552 1 == 1
553 ]""",
554          1, MatchesAll(NotEquals(1), NotEquals(2))),
555         ("1 == 1", 1,
556          MatchesAll(NotEquals(2), NotEquals(1), Equals(3), first_only=True)),
557         ]
558
559
560 class TestKeysEqual(TestCase, TestMatchersInterface):
561
562     matches_matcher = KeysEqual('foo', 'bar')
563     matches_matches = [
564         {'foo': 0, 'bar': 1},
565         ]
566     matches_mismatches = [
567         {},
568         {'foo': 0},
569         {'bar': 1},
570         {'foo': 0, 'bar': 1, 'baz': 2},
571         {'a': None, 'b': None, 'c': None},
572         ]
573
574     str_examples = [
575         ("KeysEqual('foo', 'bar')", KeysEqual('foo', 'bar')),
576         ]
577
578     describe_examples = [
579         ("['bar', 'foo'] does not match {'baz': 2, 'foo': 0, 'bar': 1}: "
580          "Keys not equal",
581          {'foo': 0, 'bar': 1, 'baz': 2}, KeysEqual('foo', 'bar')),
582         ]
583
584
585 class TestAnnotate(TestCase, TestMatchersInterface):
586
587     matches_matcher = Annotate("foo", Equals(1))
588     matches_matches = [1]
589     matches_mismatches = [2]
590
591     str_examples = [
592         ("Annotate('foo', Equals(1))", Annotate("foo", Equals(1)))]
593
594     describe_examples = [("1 != 2: foo", 2, Annotate('foo', Equals(1)))]
595
596     def test_if_message_no_message(self):
597         # Annotate.if_message returns the given matcher if there is no
598         # message.
599         matcher = Equals(1)
600         not_annotated = Annotate.if_message('', matcher)
601         self.assertIs(matcher, not_annotated)
602
603     def test_if_message_given_message(self):
604         # Annotate.if_message returns an annotated version of the matcher if a
605         # message is provided.
606         matcher = Equals(1)
607         expected = Annotate('foo', matcher)
608         annotated = Annotate.if_message('foo', matcher)
609         self.assertThat(
610             annotated,
611             MatchesStructure.fromExample(expected, 'annotation', 'matcher'))
612
613
614 class TestAnnotatedMismatch(TestCase):
615
616     run_tests_with = FullStackRunTest
617
618     def test_forwards_details(self):
619         x = Mismatch('description', {'foo': 'bar'})
620         annotated = AnnotatedMismatch("annotation", x)
621         self.assertEqual(x.get_details(), annotated.get_details())
622
623
624 class TestRaisesInterface(TestCase, TestMatchersInterface):
625
626     matches_matcher = Raises()
627     def boom():
628         raise Exception('foo')
629     matches_matches = [boom]
630     matches_mismatches = [lambda:None]
631
632     # Tricky to get function objects to render constantly, and the interfaces
633     # helper uses assertEqual rather than (for instance) DocTestMatches.
634     str_examples = []
635
636     describe_examples = []
637
638
639 class TestRaisesExceptionMatcherInterface(TestCase, TestMatchersInterface):
640
641     matches_matcher = Raises(
642         exception_matcher=MatchesException(Exception('foo')))
643     def boom_bar():
644         raise Exception('bar')
645     def boom_foo():
646         raise Exception('foo')
647     matches_matches = [boom_foo]
648     matches_mismatches = [lambda:None, boom_bar]
649
650     # Tricky to get function objects to render constantly, and the interfaces
651     # helper uses assertEqual rather than (for instance) DocTestMatches.
652     str_examples = []
653
654     describe_examples = []
655
656
657 class TestRaisesBaseTypes(TestCase):
658
659     run_tests_with = FullStackRunTest
660
661     def raiser(self):
662         raise KeyboardInterrupt('foo')
663
664     def test_KeyboardInterrupt_matched(self):
665         # When KeyboardInterrupt is matched, it is swallowed.
666         matcher = Raises(MatchesException(KeyboardInterrupt))
667         self.assertThat(self.raiser, matcher)
668
669     def test_KeyboardInterrupt_propogates(self):
670         # The default 'it raised' propogates KeyboardInterrupt.
671         match_keyb = Raises(MatchesException(KeyboardInterrupt))
672         def raise_keyb_from_match():
673             matcher = Raises()
674             matcher.match(self.raiser)
675         self.assertThat(raise_keyb_from_match, match_keyb)
676
677     def test_KeyboardInterrupt_match_Exception_propogates(self):
678         # If the raised exception isn't matched, and it is not a subclass of
679         # Exception, it is propogated.
680         match_keyb = Raises(MatchesException(KeyboardInterrupt))
681         def raise_keyb_from_match():
682             if sys.version_info > (2, 5):
683                 matcher = Raises(MatchesException(Exception))
684             else:
685                 # On Python 2.4 KeyboardInterrupt is a StandardError subclass
686                 # but should propogate from less generic exception matchers
687                 matcher = Raises(MatchesException(EnvironmentError))
688             matcher.match(self.raiser)
689         self.assertThat(raise_keyb_from_match, match_keyb)
690
691
692 class TestRaisesConvenience(TestCase):
693
694     run_tests_with = FullStackRunTest
695
696     def test_exc_type(self):
697         self.assertThat(lambda: 1/0, raises(ZeroDivisionError))
698
699     def test_exc_value(self):
700         e = RuntimeError("You lose!")
701         def raiser():
702             raise e
703         self.assertThat(raiser, raises(e))
704
705
706 class DoesNotStartWithTests(TestCase):
707
708     run_tests_with = FullStackRunTest
709
710     def test_describe(self):
711         mismatch = DoesNotStartWith("fo", "bo")
712         self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe())
713
714     def test_describe_non_ascii_unicode(self):
715         string = _u("A\xA7")
716         suffix = _u("B\xA7")
717         mismatch = DoesNotStartWith(string, suffix)
718         self.assertEqual("%s does not start with %s." % (
719             text_repr(string), text_repr(suffix)),
720             mismatch.describe())
721
722     def test_describe_non_ascii_bytes(self):
723         string = _b("A\xA7")
724         suffix = _b("B\xA7")
725         mismatch = DoesNotStartWith(string, suffix)
726         self.assertEqual("%r does not start with %r." % (string, suffix),
727             mismatch.describe())
728
729
730 class StartsWithTests(TestCase):
731
732     run_tests_with = FullStackRunTest
733
734     def test_str(self):
735         matcher = StartsWith("bar")
736         self.assertEqual("StartsWith('bar')", str(matcher))
737
738     def test_str_with_bytes(self):
739         b = _b("\xA7")
740         matcher = StartsWith(b)
741         self.assertEqual("StartsWith(%r)" % (b,), str(matcher))
742
743     def test_str_with_unicode(self):
744         u = _u("\xA7")
745         matcher = StartsWith(u)
746         self.assertEqual("StartsWith(%r)" % (u,), str(matcher))
747
748     def test_match(self):
749         matcher = StartsWith("bar")
750         self.assertIs(None, matcher.match("barf"))
751
752     def test_mismatch_returns_does_not_start_with(self):
753         matcher = StartsWith("bar")
754         self.assertIsInstance(matcher.match("foo"), DoesNotStartWith)
755
756     def test_mismatch_sets_matchee(self):
757         matcher = StartsWith("bar")
758         mismatch = matcher.match("foo")
759         self.assertEqual("foo", mismatch.matchee)
760
761     def test_mismatch_sets_expected(self):
762         matcher = StartsWith("bar")
763         mismatch = matcher.match("foo")
764         self.assertEqual("bar", mismatch.expected)
765
766
767 class DoesNotEndWithTests(TestCase):
768
769     run_tests_with = FullStackRunTest
770
771     def test_describe(self):
772         mismatch = DoesNotEndWith("fo", "bo")
773         self.assertEqual("'fo' does not end with 'bo'.", mismatch.describe())
774
775     def test_describe_non_ascii_unicode(self):
776         string = _u("A\xA7")
777         suffix = _u("B\xA7")
778         mismatch = DoesNotEndWith(string, suffix)
779         self.assertEqual("%s does not end with %s." % (
780             text_repr(string), text_repr(suffix)),
781             mismatch.describe())
782
783     def test_describe_non_ascii_bytes(self):
784         string = _b("A\xA7")
785         suffix = _b("B\xA7")
786         mismatch = DoesNotEndWith(string, suffix)
787         self.assertEqual("%r does not end with %r." % (string, suffix),
788             mismatch.describe())
789
790
791 class EndsWithTests(TestCase):
792
793     run_tests_with = FullStackRunTest
794
795     def test_str(self):
796         matcher = EndsWith("bar")
797         self.assertEqual("EndsWith('bar')", str(matcher))
798
799     def test_str_with_bytes(self):
800         b = _b("\xA7")
801         matcher = EndsWith(b)
802         self.assertEqual("EndsWith(%r)" % (b,), str(matcher))
803
804     def test_str_with_unicode(self):
805         u = _u("\xA7")
806         matcher = EndsWith(u)
807         self.assertEqual("EndsWith(%r)" % (u,), str(matcher))
808
809     def test_match(self):
810         matcher = EndsWith("arf")
811         self.assertIs(None, matcher.match("barf"))
812
813     def test_mismatch_returns_does_not_end_with(self):
814         matcher = EndsWith("bar")
815         self.assertIsInstance(matcher.match("foo"), DoesNotEndWith)
816
817     def test_mismatch_sets_matchee(self):
818         matcher = EndsWith("bar")
819         mismatch = matcher.match("foo")
820         self.assertEqual("foo", mismatch.matchee)
821
822     def test_mismatch_sets_expected(self):
823         matcher = EndsWith("bar")
824         mismatch = matcher.match("foo")
825         self.assertEqual("bar", mismatch.expected)
826
827
828 def run_doctest(obj, name):
829     p = doctest.DocTestParser()
830     t = p.get_doctest(
831         obj.__doc__, sys.modules[obj.__module__].__dict__, name, '', 0)
832     r = doctest.DocTestRunner()
833     output = StringIO()
834     r.run(t, out=output.write)
835     return r.failures, output.getvalue()
836
837
838 class TestMatchesListwise(TestCase):
839
840     run_tests_with = FullStackRunTest
841
842     def test_docstring(self):
843         failure_count, output = run_doctest(
844             MatchesListwise, "MatchesListwise")
845         if failure_count:
846             self.fail("Doctest failed with %s" % output)
847
848
849 class TestMatchesStructure(TestCase, TestMatchersInterface):
850
851     class SimpleClass:
852         def __init__(self, x, y):
853             self.x = x
854             self.y = y
855
856     matches_matcher = MatchesStructure(x=Equals(1), y=Equals(2))
857     matches_matches = [SimpleClass(1, 2)]
858     matches_mismatches = [
859         SimpleClass(2, 2),
860         SimpleClass(1, 1),
861         SimpleClass(3, 3),
862         ]
863
864     str_examples = [
865         ("MatchesStructure(x=Equals(1))", MatchesStructure(x=Equals(1))),
866         ("MatchesStructure(y=Equals(2))", MatchesStructure(y=Equals(2))),
867         ("MatchesStructure(x=Equals(1), y=Equals(2))",
868          MatchesStructure(x=Equals(1), y=Equals(2))),
869         ]
870
871     describe_examples = [
872         ("""\
873 Differences: [
874 3 != 1: x
875 ]""", SimpleClass(1, 2), MatchesStructure(x=Equals(3), y=Equals(2))),
876         ("""\
877 Differences: [
878 3 != 2: y
879 ]""", SimpleClass(1, 2), MatchesStructure(x=Equals(1), y=Equals(3))),
880         ("""\
881 Differences: [
882 0 != 1: x
883 0 != 2: y
884 ]""", SimpleClass(1, 2), MatchesStructure(x=Equals(0), y=Equals(0))),
885         ]
886
887     def test_fromExample(self):
888         self.assertThat(
889             self.SimpleClass(1, 2),
890             MatchesStructure.fromExample(self.SimpleClass(1, 3), 'x'))
891
892     def test_byEquality(self):
893         self.assertThat(
894             self.SimpleClass(1, 2),
895             MatchesStructure.byEquality(x=1))
896
897     def test_withStructure(self):
898         self.assertThat(
899             self.SimpleClass(1, 2),
900             MatchesStructure.byMatcher(LessThan, x=2))
901
902     def test_update(self):
903         self.assertThat(
904             self.SimpleClass(1, 2),
905             MatchesStructure(x=NotEquals(1)).update(x=Equals(1)))
906
907     def test_update_none(self):
908         self.assertThat(
909             self.SimpleClass(1, 2),
910             MatchesStructure(x=Equals(1), z=NotEquals(42)).update(
911                 z=None))
912
913
914 class TestMatchesRegex(TestCase, TestMatchersInterface):
915
916     matches_matcher = MatchesRegex('a|b')
917     matches_matches = ['a', 'b']
918     matches_mismatches = ['c']
919
920     str_examples = [
921         ("MatchesRegex('a|b')", MatchesRegex('a|b')),
922         ("MatchesRegex('a|b', re.M)", MatchesRegex('a|b', re.M)),
923         ("MatchesRegex('a|b', re.I|re.M)", MatchesRegex('a|b', re.I|re.M)),
924         ("MatchesRegex(%r)" % (_b("\xA7"),), MatchesRegex(_b("\xA7"))),
925         ("MatchesRegex(%r)" % (_u("\xA7"),), MatchesRegex(_u("\xA7"))),
926         ]
927
928     describe_examples = [
929         ("'c' does not match /a|b/", 'c', MatchesRegex('a|b')),
930         ("'c' does not match /a\d/", 'c', MatchesRegex(r'a\d')),
931         ("%r does not match /\\s+\\xa7/" % (_b('c'),),
932             _b('c'), MatchesRegex(_b("\\s+\xA7"))),
933         ("%r does not match /\\s+\\xa7/" % (_u('c'),),
934             _u('c'), MatchesRegex(_u("\\s+\xA7"))),
935         ]
936
937
938 class TestMatchesSetwise(TestCase):
939
940     run_tests_with = FullStackRunTest
941
942     def assertMismatchWithDescriptionMatching(self, value, matcher,
943                                               description_matcher):
944         mismatch = matcher.match(value)
945         if mismatch is None:
946             self.fail("%s matched %s" % (matcher, value))
947         actual_description = mismatch.describe()
948         self.assertThat(
949             actual_description,
950             Annotate(
951                 "%s matching %s" % (matcher, value),
952                 description_matcher))
953
954     def test_matches(self):
955         self.assertIs(
956             None, MatchesSetwise(Equals(1), Equals(2)).match([2, 1]))
957
958     def test_mismatches(self):
959         self.assertMismatchWithDescriptionMatching(
960             [2, 3], MatchesSetwise(Equals(1), Equals(2)),
961             MatchesRegex('.*There was 1 mismatch$', re.S))
962
963     def test_too_many_matchers(self):
964         self.assertMismatchWithDescriptionMatching(
965             [2, 3], MatchesSetwise(Equals(1), Equals(2), Equals(3)),
966             Equals('There was 1 matcher left over: Equals(1)'))
967
968     def test_too_many_values(self):
969         self.assertMismatchWithDescriptionMatching(
970             [1, 2, 3], MatchesSetwise(Equals(1), Equals(2)),
971             Equals('There was 1 value left over: [3]'))
972
973     def test_two_too_many_matchers(self):
974         self.assertMismatchWithDescriptionMatching(
975             [3], MatchesSetwise(Equals(1), Equals(2), Equals(3)),
976             MatchesRegex(
977                 'There were 2 matchers left over: Equals\([12]\), '
978                 'Equals\([12]\)'))
979
980     def test_two_too_many_values(self):
981         self.assertMismatchWithDescriptionMatching(
982             [1, 2, 3, 4], MatchesSetwise(Equals(1), Equals(2)),
983             MatchesRegex(
984                 'There were 2 values left over: \[[34], [34]\]'))
985
986     def test_mismatch_and_too_many_matchers(self):
987         self.assertMismatchWithDescriptionMatching(
988             [2, 3], MatchesSetwise(Equals(0), Equals(1), Equals(2)),
989             MatchesRegex(
990                 '.*There was 1 mismatch and 1 extra matcher: Equals\([01]\)',
991                 re.S))
992
993     def test_mismatch_and_too_many_values(self):
994         self.assertMismatchWithDescriptionMatching(
995             [2, 3, 4], MatchesSetwise(Equals(1), Equals(2)),
996             MatchesRegex(
997                 '.*There was 1 mismatch and 1 extra value: \[[34]\]',
998                 re.S))
999
1000     def test_mismatch_and_two_too_many_matchers(self):
1001         self.assertMismatchWithDescriptionMatching(
1002             [3, 4], MatchesSetwise(
1003                 Equals(0), Equals(1), Equals(2), Equals(3)),
1004             MatchesRegex(
1005                 '.*There was 1 mismatch and 2 extra matchers: '
1006                 'Equals\([012]\), Equals\([012]\)', re.S))
1007
1008     def test_mismatch_and_two_too_many_values(self):
1009         self.assertMismatchWithDescriptionMatching(
1010             [2, 3, 4, 5], MatchesSetwise(Equals(1), Equals(2)),
1011             MatchesRegex(
1012                 '.*There was 1 mismatch and 2 extra values: \[[145], [145]\]',
1013                 re.S))
1014
1015
1016 class TestAfterPreprocessing(TestCase, TestMatchersInterface):
1017
1018     def parity(x):
1019         return x % 2
1020
1021     matches_matcher = AfterPreprocessing(parity, Equals(1))
1022     matches_matches = [3, 5]
1023     matches_mismatches = [2]
1024
1025     str_examples = [
1026         ("AfterPreprocessing(<function parity>, Equals(1))",
1027          AfterPreprocessing(parity, Equals(1))),
1028         ]
1029
1030     describe_examples = [
1031         ("1 != 0: after <function parity> on 2", 2,
1032          AfterPreprocessing(parity, Equals(1))),
1033         ("1 != 0", 2,
1034          AfterPreprocessing(parity, Equals(1), annotate=False)),
1035         ]
1036
1037
1038 class TestMismatchDecorator(TestCase):
1039
1040     run_tests_with = FullStackRunTest
1041
1042     def test_forwards_description(self):
1043         x = Mismatch("description", {'foo': 'bar'})
1044         decorated = MismatchDecorator(x)
1045         self.assertEqual(x.describe(), decorated.describe())
1046
1047     def test_forwards_details(self):
1048         x = Mismatch("description", {'foo': 'bar'})
1049         decorated = MismatchDecorator(x)
1050         self.assertEqual(x.get_details(), decorated.get_details())
1051
1052     def test_repr(self):
1053         x = Mismatch("description", {'foo': 'bar'})
1054         decorated = MismatchDecorator(x)
1055         self.assertEqual(
1056             '<testtools.matchers.MismatchDecorator(%r)>' % (x,),
1057             repr(decorated))
1058
1059
1060 class TestAllMatch(TestCase, TestMatchersInterface):
1061
1062     matches_matcher = AllMatch(LessThan(10))
1063     matches_matches = [
1064         [9, 9, 9],
1065         (9, 9),
1066         iter([9, 9, 9, 9, 9]),
1067         ]
1068     matches_mismatches = [
1069         [11, 9, 9],
1070         iter([9, 12, 9, 11]),
1071         ]
1072
1073     str_examples = [
1074         ("AllMatch(LessThan(12))", AllMatch(LessThan(12))),
1075         ]
1076
1077     describe_examples = [
1078         ('Differences: [\n'
1079          '10 is not > 11\n'
1080          '10 is not > 10\n'
1081          ']',
1082          [11, 9, 10],
1083          AllMatch(LessThan(10))),
1084         ]
1085
1086
1087 class PathHelpers(object):
1088
1089     def mkdtemp(self):
1090         directory = tempfile.mkdtemp()
1091         self.addCleanup(shutil.rmtree, directory)
1092         return directory
1093
1094     def create_file(self, filename, contents=''):
1095         fp = open(filename, 'w')
1096         try:
1097             fp.write(contents)
1098         finally:
1099             fp.close()
1100
1101     def touch(self, filename):
1102         return self.create_file(filename)
1103
1104
1105 class TestPathExists(TestCase, PathHelpers):
1106
1107     def test_exists(self):
1108         tempdir = self.mkdtemp()
1109         self.assertThat(tempdir, PathExists())
1110
1111     def test_not_exists(self):
1112         doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
1113         mismatch = PathExists().match(doesntexist)
1114         self.assertThat(
1115             "%s does not exist." % doesntexist, Equals(mismatch.describe()))
1116
1117
1118 class TestDirExists(TestCase, PathHelpers):
1119
1120     def test_exists(self):
1121         tempdir = self.mkdtemp()
1122         self.assertThat(tempdir, DirExists())
1123
1124     def test_not_exists(self):
1125         doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
1126         mismatch = DirExists().match(doesntexist)
1127         self.assertThat(
1128             PathExists().match(doesntexist).describe(),
1129             Equals(mismatch.describe()))
1130
1131     def test_not_a_directory(self):
1132         filename = os.path.join(self.mkdtemp(), 'foo')
1133         self.touch(filename)
1134         mismatch = DirExists().match(filename)
1135         self.assertThat(
1136             "%s is not a directory." % filename, Equals(mismatch.describe()))
1137
1138
1139 class TestFileExists(TestCase, PathHelpers):
1140
1141     def test_exists(self):
1142         tempdir = self.mkdtemp()
1143         filename = os.path.join(tempdir, 'filename')
1144         self.touch(filename)
1145         self.assertThat(filename, FileExists())
1146
1147     def test_not_exists(self):
1148         doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
1149         mismatch = FileExists().match(doesntexist)
1150         self.assertThat(
1151             PathExists().match(doesntexist).describe(),
1152             Equals(mismatch.describe()))
1153
1154     def test_not_a_file(self):
1155         tempdir = self.mkdtemp()
1156         mismatch = FileExists().match(tempdir)
1157         self.assertThat(
1158             "%s is not a file." % tempdir, Equals(mismatch.describe()))
1159
1160
1161 class TestDirContains(TestCase, PathHelpers):
1162
1163     def test_empty(self):
1164         tempdir = self.mkdtemp()
1165         self.assertThat(tempdir, DirContains([]))
1166
1167     def test_not_exists(self):
1168         doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
1169         mismatch = DirContains([]).match(doesntexist)
1170         self.assertThat(
1171             PathExists().match(doesntexist).describe(),
1172             Equals(mismatch.describe()))
1173
1174     def test_contains_files(self):
1175         tempdir = self.mkdtemp()
1176         self.touch(os.path.join(tempdir, 'foo'))
1177         self.touch(os.path.join(tempdir, 'bar'))
1178         self.assertThat(tempdir, DirContains(['bar', 'foo']))
1179
1180     def test_matcher(self):
1181         tempdir = self.mkdtemp()
1182         self.touch(os.path.join(tempdir, 'foo'))
1183         self.touch(os.path.join(tempdir, 'bar'))
1184         self.assertThat(tempdir, DirContains(matcher=Contains('bar')))
1185
1186     def test_neither_specified(self):
1187         self.assertRaises(AssertionError, DirContains)
1188
1189     def test_both_specified(self):
1190         self.assertRaises(
1191             AssertionError, DirContains, filenames=[], matcher=Contains('a'))
1192
1193     def test_does_not_contain_files(self):
1194         tempdir = self.mkdtemp()
1195         self.touch(os.path.join(tempdir, 'foo'))
1196         mismatch = DirContains(['bar', 'foo']).match(tempdir)
1197         self.assertThat(
1198             Equals(['bar', 'foo']).match(['foo']).describe(),
1199             Equals(mismatch.describe()))
1200
1201
1202 class TestFileContains(TestCase, PathHelpers):
1203
1204     def test_not_exists(self):
1205         doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
1206         mismatch = FileContains('').match(doesntexist)
1207         self.assertThat(
1208             PathExists().match(doesntexist).describe(),
1209             Equals(mismatch.describe()))
1210
1211     def test_contains(self):
1212         tempdir = self.mkdtemp()
1213         filename = os.path.join(tempdir, 'foo')
1214         self.create_file(filename, 'Hello World!')
1215         self.assertThat(filename, FileContains('Hello World!'))
1216
1217     def test_matcher(self):
1218         tempdir = self.mkdtemp()
1219         filename = os.path.join(tempdir, 'foo')
1220         self.create_file(filename, 'Hello World!')
1221         self.assertThat(
1222             filename, FileContains(matcher=DocTestMatches('Hello World!')))
1223
1224     def test_neither_specified(self):
1225         self.assertRaises(AssertionError, FileContains)
1226
1227     def test_both_specified(self):
1228         self.assertRaises(
1229             AssertionError, FileContains, contents=[], matcher=Contains('a'))
1230
1231     def test_does_not_contain(self):
1232         tempdir = self.mkdtemp()
1233         filename = os.path.join(tempdir, 'foo')
1234         self.create_file(filename, 'Goodbye Cruel World!')
1235         mismatch = FileContains('Hello World!').match(filename)
1236         self.assertThat(
1237             Equals('Hello World!').match('Goodbye Cruel World!').describe(),
1238             Equals(mismatch.describe()))
1239
1240
1241 def is_even(x):
1242     return x % 2 == 0
1243
1244
1245 class TestMatchesPredicate(TestCase, TestMatchersInterface):
1246
1247     matches_matcher = MatchesPredicate(is_even, "%s is not even")
1248     matches_matches = [2, 4, 6, 8]
1249     matches_mismatches = [3, 5, 7, 9]
1250
1251     str_examples = [
1252         ("MatchesPredicate(%r, %r)" % (is_even, "%s is not even"),
1253          MatchesPredicate(is_even, "%s is not even")),
1254         ]
1255
1256     describe_examples = [
1257         ('7 is not even', 7, MatchesPredicate(is_even, "%s is not even")),
1258         ]
1259
1260
1261 class TestTarballContains(TestCase, PathHelpers):
1262
1263     def test_match(self):
1264         tempdir = self.mkdtemp()
1265         in_temp_dir = lambda x: os.path.join(tempdir, x)
1266         self.touch(in_temp_dir('a'))
1267         self.touch(in_temp_dir('b'))
1268         tarball = tarfile.open(in_temp_dir('foo.tar.gz'), 'w')
1269         tarball.add(in_temp_dir('a'), 'a')
1270         tarball.add(in_temp_dir('b'), 'b')
1271         tarball.close()
1272         self.assertThat(
1273             in_temp_dir('foo.tar.gz'), TarballContains(['b', 'a']))
1274
1275     def test_mismatch(self):
1276         tempdir = self.mkdtemp()
1277         in_temp_dir = lambda x: os.path.join(tempdir, x)
1278         self.touch(in_temp_dir('a'))
1279         self.touch(in_temp_dir('b'))
1280         tarball = tarfile.open(in_temp_dir('foo.tar.gz'), 'w')
1281         tarball.add(in_temp_dir('a'), 'a')
1282         tarball.add(in_temp_dir('b'), 'b')
1283         tarball.close()
1284         mismatch = TarballContains(['d', 'c']).match(in_temp_dir('foo.tar.gz'))
1285         self.assertEqual(
1286             mismatch.describe(),
1287             Equals(['c', 'd']).match(['a', 'b']).describe())
1288
1289
1290 class TestSamePath(TestCase, PathHelpers):
1291
1292     def test_same_string(self):
1293         self.assertThat('foo', SamePath('foo'))
1294
1295     def test_relative_and_absolute(self):
1296         path = 'foo'
1297         abspath = os.path.abspath(path)
1298         self.assertThat(path, SamePath(abspath))
1299         self.assertThat(abspath, SamePath(path))
1300
1301     def test_real_path(self):
1302         symlink = getattr(os, 'symlink', None)
1303         skipIf(symlink is None, "No symlink support")
1304         tempdir = self.mkdtemp()
1305         source = os.path.join(tempdir, 'source')
1306         self.touch(source)
1307         target = os.path.join(tempdir, 'target')
1308         symlink(source, target)
1309         self.assertThat(source, SamePath(target))
1310         self.assertThat(target, SamePath(source))
1311
1312
1313 class TestHasPermissions(TestCase, PathHelpers):
1314
1315     def test_match(self):
1316         tempdir = self.mkdtemp()
1317         filename = os.path.join(tempdir, 'filename')
1318         self.touch(filename)
1319         permissions = oct(os.stat(filename).st_mode)[-4:]
1320         self.assertThat(filename, HasPermissions(permissions))
1321
1322
1323 def test_suite():
1324     from unittest import TestLoader
1325     return TestLoader().loadTestsFromName(__name__)