1# Copyright (c) 2008-2012 testtools developers. See LICENSE for details.
2
3import os
4import shutil
5import tarfile
6import tempfile
7
8from testtools import TestCase
9from testtools.matchers import (
10    Contains,
11    DocTestMatches,
12    Equals,
13    )
14from testtools.matchers._filesystem import (
15    DirContains,
16    DirExists,
17    FileContains,
18    FileExists,
19    HasPermissions,
20    PathExists,
21    SamePath,
22    TarballContains,
23    )
24
25
26class PathHelpers(object):
27
28    def mkdtemp(self):
29        directory = tempfile.mkdtemp()
30        self.addCleanup(shutil.rmtree, directory)
31        return directory
32
33    def create_file(self, filename, contents=''):
34        fp = open(filename, 'w')
35        try:
36            fp.write(contents)
37        finally:
38            fp.close()
39
40    def touch(self, filename):
41        return self.create_file(filename)
42
43
44class TestPathExists(TestCase, PathHelpers):
45
46    def test_exists(self):
47        tempdir = self.mkdtemp()
48        self.assertThat(tempdir, PathExists())
49
50    def test_not_exists(self):
51        doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
52        mismatch = PathExists().match(doesntexist)
53        self.assertThat(
54            "%s does not exist." % doesntexist, Equals(mismatch.describe()))
55
56
57class TestDirExists(TestCase, PathHelpers):
58
59    def test_exists(self):
60        tempdir = self.mkdtemp()
61        self.assertThat(tempdir, DirExists())
62
63    def test_not_exists(self):
64        doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
65        mismatch = DirExists().match(doesntexist)
66        self.assertThat(
67            PathExists().match(doesntexist).describe(),
68            Equals(mismatch.describe()))
69
70    def test_not_a_directory(self):
71        filename = os.path.join(self.mkdtemp(), 'foo')
72        self.touch(filename)
73        mismatch = DirExists().match(filename)
74        self.assertThat(
75            "%s is not a directory." % filename, Equals(mismatch.describe()))
76
77
78class TestFileExists(TestCase, PathHelpers):
79
80    def test_exists(self):
81        tempdir = self.mkdtemp()
82        filename = os.path.join(tempdir, 'filename')
83        self.touch(filename)
84        self.assertThat(filename, FileExists())
85
86    def test_not_exists(self):
87        doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
88        mismatch = FileExists().match(doesntexist)
89        self.assertThat(
90            PathExists().match(doesntexist).describe(),
91            Equals(mismatch.describe()))
92
93    def test_not_a_file(self):
94        tempdir = self.mkdtemp()
95        mismatch = FileExists().match(tempdir)
96        self.assertThat(
97            "%s is not a file." % tempdir, Equals(mismatch.describe()))
98
99
100class TestDirContains(TestCase, PathHelpers):
101
102    def test_empty(self):
103        tempdir = self.mkdtemp()
104        self.assertThat(tempdir, DirContains([]))
105
106    def test_not_exists(self):
107        doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
108        mismatch = DirContains([]).match(doesntexist)
109        self.assertThat(
110            PathExists().match(doesntexist).describe(),
111            Equals(mismatch.describe()))
112
113    def test_contains_files(self):
114        tempdir = self.mkdtemp()
115        self.touch(os.path.join(tempdir, 'foo'))
116        self.touch(os.path.join(tempdir, 'bar'))
117        self.assertThat(tempdir, DirContains(['bar', 'foo']))
118
119    def test_matcher(self):
120        tempdir = self.mkdtemp()
121        self.touch(os.path.join(tempdir, 'foo'))
122        self.touch(os.path.join(tempdir, 'bar'))
123        self.assertThat(tempdir, DirContains(matcher=Contains('bar')))
124
125    def test_neither_specified(self):
126        self.assertRaises(AssertionError, DirContains)
127
128    def test_both_specified(self):
129        self.assertRaises(
130            AssertionError, DirContains, filenames=[], matcher=Contains('a'))
131
132    def test_does_not_contain_files(self):
133        tempdir = self.mkdtemp()
134        self.touch(os.path.join(tempdir, 'foo'))
135        mismatch = DirContains(['bar', 'foo']).match(tempdir)
136        self.assertThat(
137            Equals(['bar', 'foo']).match(['foo']).describe(),
138            Equals(mismatch.describe()))
139
140
141class TestFileContains(TestCase, PathHelpers):
142
143    def test_not_exists(self):
144        doesntexist = os.path.join(self.mkdtemp(), 'doesntexist')
145        mismatch = FileContains('').match(doesntexist)
146        self.assertThat(
147            PathExists().match(doesntexist).describe(),
148            Equals(mismatch.describe()))
149
150    def test_contains(self):
151        tempdir = self.mkdtemp()
152        filename = os.path.join(tempdir, 'foo')
153        self.create_file(filename, 'Hello World!')
154        self.assertThat(filename, FileContains('Hello World!'))
155
156    def test_matcher(self):
157        tempdir = self.mkdtemp()
158        filename = os.path.join(tempdir, 'foo')
159        self.create_file(filename, 'Hello World!')
160        self.assertThat(
161            filename, FileContains(matcher=DocTestMatches('Hello World!')))
162
163    def test_neither_specified(self):
164        self.assertRaises(AssertionError, FileContains)
165
166    def test_both_specified(self):
167        self.assertRaises(
168            AssertionError, FileContains, contents=[], matcher=Contains('a'))
169
170    def test_does_not_contain(self):
171        tempdir = self.mkdtemp()
172        filename = os.path.join(tempdir, 'foo')
173        self.create_file(filename, 'Goodbye Cruel World!')
174        mismatch = FileContains('Hello World!').match(filename)
175        self.assertThat(
176            Equals('Hello World!').match('Goodbye Cruel World!').describe(),
177            Equals(mismatch.describe()))
178class TestTarballContains(TestCase, PathHelpers):
179
180    def test_match(self):
181        tempdir = self.mkdtemp()
182        in_temp_dir = lambda x: os.path.join(tempdir, x)
183        self.touch(in_temp_dir('a'))
184        self.touch(in_temp_dir('b'))
185        tarball = tarfile.open(in_temp_dir('foo.tar.gz'), 'w')
186        tarball.add(in_temp_dir('a'), 'a')
187        tarball.add(in_temp_dir('b'), 'b')
188        tarball.close()
189        self.assertThat(
190            in_temp_dir('foo.tar.gz'), TarballContains(['b', 'a']))
191
192    def test_mismatch(self):
193        tempdir = self.mkdtemp()
194        in_temp_dir = lambda x: os.path.join(tempdir, x)
195        self.touch(in_temp_dir('a'))
196        self.touch(in_temp_dir('b'))
197        tarball = tarfile.open(in_temp_dir('foo.tar.gz'), 'w')
198        tarball.add(in_temp_dir('a'), 'a')
199        tarball.add(in_temp_dir('b'), 'b')
200        tarball.close()
201        mismatch = TarballContains(['d', 'c']).match(in_temp_dir('foo.tar.gz'))
202        self.assertEqual(
203            mismatch.describe(),
204            Equals(['c', 'd']).match(['a', 'b']).describe())
205
206
207class TestSamePath(TestCase, PathHelpers):
208
209    def test_same_string(self):
210        self.assertThat('foo', SamePath('foo'))
211
212    def test_relative_and_absolute(self):
213        path = 'foo'
214        abspath = os.path.abspath(path)
215        self.assertThat(path, SamePath(abspath))
216        self.assertThat(abspath, SamePath(path))
217
218    def test_real_path(self):
219        tempdir = self.mkdtemp()
220        source = os.path.join(tempdir, 'source')
221        self.touch(source)
222        target = os.path.join(tempdir, 'target')
223        try:
224            os.symlink(source, target)
225        except (AttributeError, NotImplementedError):
226            self.skip("No symlink support")
227        self.assertThat(source, SamePath(target))
228        self.assertThat(target, SamePath(source))
229
230
231class TestHasPermissions(TestCase, PathHelpers):
232
233    def test_match(self):
234        tempdir = self.mkdtemp()
235        filename = os.path.join(tempdir, 'filename')
236        self.touch(filename)
237        permissions = oct(os.stat(filename).st_mode)[-4:]
238        self.assertThat(filename, HasPermissions(permissions))
239
240
241def test_suite():
242    from unittest import TestLoader
243    return TestLoader().loadTestsFromName(__name__)
244