summaryrefslogtreecommitdiff
path: root/lib/fixtures/tests/_fixtures/test_tempdir.py
blob: c253a680fbe9db4ee44943471fbe305af5d08b55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#  fixtures: Fixtures with cleanups for testing and convenience.
#
# Copyright (c) 2010, 2012  Robert Collins <robertc@robertcollins.net>
# 
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
# license you chose for the specific language governing permissions and
# limitations under that license.

import os
import tempfile

import testtools
from testtools.matchers import (
    DirContains,
    DirExists,
    FileContains,
    StartsWith,
    )

from fixtures import (
    NestedTempfile,
    TempDir,
    )
from fixtures._fixtures.tempdir import (
    create_normal_shape,
    normalize_entry,
    normalize_shape,
    )
from fixtures.tests.helpers import HasNoAttribute


class TestTempDir(testtools.TestCase):

    def test_basic(self):
        fixture = TempDir()
        self.assertThat(fixture, HasNoAttribute('path'))
        fixture.setUp()
        try:
            path = fixture.path
            self.assertTrue(os.path.isdir(path))
        finally:
            fixture.cleanUp()
            self.assertFalse(os.path.isdir(path))

    def test_under_dir(self):
        root = self.useFixture(TempDir()).path
        fixture = TempDir(root)
        fixture.setUp()
        with fixture:
            self.assertThat(fixture.path, StartsWith(root))


class NestedTempfileTest(testtools.TestCase):
    """Tests for `NestedTempfile`."""

    def test_normal(self):
        # The temp directory is removed when the context is exited.
        starting_tempdir = tempfile.gettempdir()
        with NestedTempfile():
            self.assertEqual(tempfile.tempdir, tempfile.gettempdir())
            self.assertNotEqual(starting_tempdir, tempfile.tempdir)
            self.assertTrue(os.path.isdir(tempfile.tempdir))
            nested_tempdir = tempfile.tempdir
        self.assertEqual(tempfile.tempdir, tempfile.gettempdir())
        self.assertEqual(starting_tempdir, tempfile.tempdir)
        self.assertFalse(os.path.isdir(nested_tempdir))

    def test_exception(self):
        # The temp directory is removed when the context is exited, even if
        # the code running in context raises an exception.
        class ContrivedException(Exception):
            pass
        try:
            with NestedTempfile():
                nested_tempdir = tempfile.tempdir
                raise ContrivedException
        except ContrivedException:
            self.assertFalse(os.path.isdir(nested_tempdir))


class TestFileTree(testtools.TestCase):

    def test_out_of_order(self):
        # If a file or a subdirectory is listed before its parent directory,
        # that doesn't matter.  We'll create the directory first.
        fixture = TempDir()
        with fixture:
            fixture.make_tree('a/b/', 'a/')
            path = fixture.path
            self.assertThat(path, DirContains(['a']))
            self.assertThat(os.path.join(path, 'a'), DirContains(['b']))
            self.assertThat(os.path.join(path, 'a', 'b'), DirExists())

    def test_not_even_creating_parents(self):
        fixture = TempDir()
        with fixture:
            fixture.make_tree('a/b/foo.txt', 'c/d/e/')
            path = fixture.path
            self.assertThat(
                os.path.join(path, 'a', 'b', 'foo.txt'),
                FileContains("The file 'a/b/foo.txt'."))
            self.assertThat(os.path.join(path, 'c', 'd', 'e'), DirExists())


class TestNormalizeEntry(testtools.TestCase):

    def test_file_as_tuple(self):
        # A tuple of filenames and contents is already normalized.
        entry = normalize_entry(('foo', 'foo contents'))
        self.assertEqual(('foo', 'foo contents'), entry)

    def test_directories_as_tuples(self):
        # A tuple of directory name and None is already normalized.
        directory = normalize_entry(('foo/', None))
        self.assertEqual(('foo/', None), directory)

    def test_directories_as_singletons(self):
        # A singleton tuple of directory name is normalized to a 2-tuple of
        # the directory name and None.
        directory = normalize_entry(('foo/',))
        self.assertEqual(('foo/', None), directory)

    def test_directories_as_strings(self):
        # If directories are just given as strings, then they are normalized
        # to tuples of directory names and None.
        directory = normalize_entry('foo/')
        self.assertEqual(('foo/', None), directory)

    def test_directories_with_content(self):
        # If we're given a directory with content, we raise an error, since
        # it's ambiguous and we don't want to guess.
        bad_entry = ('dir/', "stuff")
        e = self.assertRaises(ValueError, normalize_entry, bad_entry)
        self.assertEqual(
            "Directories must end with '/' and have no content, files do not "
            "end with '/' and must have content, got %r" % (bad_entry,),
            str(e))

    def test_filenames_as_strings(self):
        # If file names are just given as strings, then they are normalized to
        # tuples of filenames and made-up contents.
        entry = normalize_entry('foo')
        self.assertEqual(('foo', "The file 'foo'."), entry)

    def test_filenames_as_singletons(self):
        # A singleton tuple of a filename is normalized to a 2-tuple of
        # the file name and made-up contents.
        entry = normalize_entry(('foo',))
        self.assertEqual(('foo', "The file 'foo'."), entry)

    def test_filenames_without_content(self):
        # If we're given a filename without content, we raise an error, since
        # it's ambiguous and we don't want to guess.
        bad_entry = ('filename', None)
        e = self.assertRaises(ValueError, normalize_entry, bad_entry)
        self.assertEqual(
            "Directories must end with '/' and have no content, files do not "
            "end with '/' and must have content, got %r" % (bad_entry,),
            str(e))

    def test_too_long_tuple(self):
        bad_entry = ('foo', 'bar', 'baz')
        e = self.assertRaises(ValueError, normalize_entry, bad_entry)
        self.assertEqual(
            "Invalid file or directory description: %r" % (bad_entry,),
            str(e))


class TestNormalizeShape(testtools.TestCase):

    def test_empty(self):
        # The normal form of an empty list is the empty list.
        empty = normalize_shape([])
        self.assertEqual([], empty)

    def test_sorts_entries(self):
        # The normal form a list of entries is the sorted list of normal
        # entries.
        entries = normalize_shape(['a/b/', 'a/'])
        self.assertEqual([('a/', None), ('a/b/', None)], entries)


class TestCreateNormalShape(testtools.TestCase):

    def test_empty(self):
        tempdir = self.useFixture(TempDir()).path
        create_normal_shape(tempdir, [])
        self.assertThat(tempdir, DirContains([]))

    def test_creates_files(self):
        # When given a list of file specifications, it creates those files
        # underneath the temporary directory.
        path = self.useFixture(TempDir()).path
        create_normal_shape(path, [('a', 'foo'), ('b', 'bar')])
        self.assertThat(path, DirContains(['a', 'b']))
        self.assertThat(os.path.join(path, 'a'), FileContains('foo'))
        self.assertThat(os.path.join(path, 'b'), FileContains('bar'))

    def test_creates_directories(self):
        # When given directory specifications, it creates those directories.
        path = self.useFixture(TempDir()).path
        create_normal_shape(path, [('a/', None), ('b/', None)])
        self.assertThat(path, DirContains(['a', 'b']))
        self.assertThat(os.path.join(path, 'a'), DirExists())
        self.assertThat(os.path.join(path, 'b'), DirExists())

    def test_creates_parent_directories(self):
        # If the parents of a file or directory don't exist, they get created
        # too.
        path = self.useFixture(TempDir()).path
        create_normal_shape(path, [('a/b/', None), ('c/d.txt', 'text')])
        self.assertThat(path, DirContains(['a', 'c']))
        self.assertThat(os.path.join(path, 'a'), DirContains('b'))
        self.assertThat(os.path.join(path, 'a', 'b'), DirExists())
        self.assertThat(os.path.join(path, 'c'), DirExists())
        self.assertThat(os.path.join(path, 'c', 'd.txt'), FileContains('text'))