/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for repository commit builder."""
18
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
19
from errno import EISDIR
20
import os
21
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
22
from bzrlib import inventory
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
23
from bzrlib.errors import NonAsciiRevisionId, CannotSetRevisionId
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
24
from bzrlib.repository import CommitBuilder
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
25
from bzrlib import tests
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
26
from bzrlib.tests.repository_implementations.test_repository import TestCaseWithRepository
27
28
29
class TestCommitBuilder(TestCaseWithRepository):
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
30
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
31
    def test_get_commit_builder(self):
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
32
        branch = self.make_branch('.')
33
        branch.repository.lock_write()
34
        builder = branch.repository.get_commit_builder(
35
            branch, [], branch.get_config())
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
36
        self.assertIsInstance(builder, CommitBuilder)
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
37
        branch.repository.commit_write_group()
38
        branch.repository.unlock()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
39
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
40
    def record_root(self, builder, tree):
41
        if builder.record_root_entry is True:
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
42
            tree.lock_read()
43
            try:
44
                ie = tree.inventory.root
45
            finally:
46
                tree.unlock()
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
47
            parent_tree = tree.branch.repository.revision_tree(None)
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
48
            parent_invs = []
2776.4.4 by Robert Collins
Move content summary generation outside of record_entry_contents.
49
            builder.record_entry_contents(ie, parent_invs, '', tree,
50
                tree.path_content_summary(''))
1731.1.33 by Aaron Bentley
Revert no-special-root changes
51
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
52
    def test_finish_inventory(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
53
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
54
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
55
        try:
56
            builder = tree.branch.get_commit_builder([])
57
            self.record_root(builder, tree)
58
            builder.finish_inventory()
59
            tree.branch.repository.commit_write_group()
60
        finally:
61
            tree.unlock()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
62
2749.3.1 by Jelmer Vernooij
Add CommitBuilder.abort().
63
    def test_abort(self):
64
        tree = self.make_branch_and_tree(".")
65
        tree.lock_write()
66
        try:
67
            builder = tree.branch.get_commit_builder([])
68
            self.record_root(builder, tree)
69
            builder.finish_inventory()
70
            builder.abort()
71
        finally:
72
            tree.unlock()
73
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
74
    def test_commit_message(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
75
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
76
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
77
        try:
78
            builder = tree.branch.get_commit_builder([])
79
            self.record_root(builder, tree)
80
            builder.finish_inventory()
81
            rev_id = builder.commit('foo bar blah')
82
        finally:
83
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
84
        rev = tree.branch.repository.get_revision(rev_id)
85
        self.assertEqual('foo bar blah', rev.message)
86
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
87
    def test_commit_with_revision_id(self):
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
88
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
89
        tree.lock_write()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
90
        try:
2617.6.8 by Robert Collins
Review feedback and documentation.
91
            # use a unicode revision id to test more corner cases.
92
            # The repository layer is meant to handle this.
93
            revision_id = u'\xc8abc'.encode('utf8')
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
94
            try:
2617.6.8 by Robert Collins
Review feedback and documentation.
95
                try:
96
                    builder = tree.branch.get_commit_builder([],
97
                        revision_id=revision_id)
98
                except NonAsciiRevisionId:
99
                    revision_id = 'abc'
100
                    builder = tree.branch.get_commit_builder([],
101
                        revision_id=revision_id)
102
            except CannotSetRevisionId:
103
                # This format doesn't support supplied revision ids
104
                return
105
            self.record_root(builder, tree)
106
            builder.finish_inventory()
107
            self.assertEqual(revision_id, builder.commit('foo bar'))
108
        finally:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
109
            tree.unlock()
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
110
        self.assertTrue(tree.branch.repository.has_revision(revision_id))
111
        # the revision id must be set on the inventory when saving it. This
112
        # does not precisely test that - a repository that wants to can add it
113
        # on deserialisation, but thats all the current contract guarantees
114
        # anyway.
115
        self.assertEqual(revision_id,
116
            tree.branch.repository.get_inventory(revision_id).revision_id)
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
117
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
118
    def test_commit_without_root(self):
119
        """This should cause a deprecation warning, not an assertion failure"""
120
        tree = self.make_branch_and_tree(".")
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
121
        tree.lock_write()
122
        try:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
123
            if tree.branch.repository.supports_rich_root():
124
                raise tests.TestSkipped('Format requires root')
125
            self.build_tree(['foo'])
126
            tree.add('foo', 'foo-id')
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
127
            entry = tree.inventory['foo-id']
128
            builder = tree.branch.get_commit_builder([])
129
            self.callDeprecated(['Root entry should be supplied to'
130
                ' record_entry_contents, as of bzr 0.10.'],
2776.4.4 by Robert Collins
Move content summary generation outside of record_entry_contents.
131
                builder.record_entry_contents, entry, [], 'foo', tree,
132
                    tree.path_content_summary('foo'))
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
133
            builder.finish_inventory()
134
            rev_id = builder.commit('foo bar')
135
        finally:
136
            tree.unlock()
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
137
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
138
    def test_commit(self):
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
139
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
140
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
141
        try:
142
            builder = tree.branch.get_commit_builder([])
143
            self.record_root(builder, tree)
144
            builder.finish_inventory()
145
            rev_id = builder.commit('foo bar')
146
        finally:
147
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
148
        self.assertNotEqual(None, rev_id)
149
        self.assertTrue(tree.branch.repository.has_revision(rev_id))
1757.1.2 by Robert Collins
Bugfix CommitBuilders recording of the inventory revision id.
150
        # the revision id must be set on the inventory when saving it. This does not
151
        # precisely test that - a repository that wants to can add it on deserialisation,
152
        # but thats all the current contract guarantees anyway.
153
        self.assertEqual(rev_id, tree.branch.repository.get_inventory(rev_id).revision_id)
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
154
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
155
    def test_revision_tree(self):
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
156
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
157
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
158
        try:
159
            builder = tree.branch.get_commit_builder([])
160
            self.record_root(builder, tree)
161
            builder.finish_inventory()
162
            rev_id = builder.commit('foo bar')
163
        finally:
164
            tree.unlock()
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
165
        rev_tree = builder.revision_tree()
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
166
        # Just a couple simple tests to ensure that it actually follows
167
        # the RevisionTree api.
168
        self.assertEqual(rev_id, rev_tree.get_revision_id())
169
        self.assertEqual([], rev_tree.get_parent_ids())
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
170
171
    def test_root_entry_has_revision(self):
172
        # test the root revision created and put in the basis
173
        # has the right rev id.
174
        tree = self.make_branch_and_tree('.')
175
        rev_id = tree.commit('message')
176
        basis_tree = tree.basis_tree()
177
        basis_tree.lock_read()
178
        self.addCleanup(basis_tree.unlock)
179
        self.assertEqual(rev_id, basis_tree.inventory.root.revision)
180
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
181
    def _get_revtrees(self, tree, revision_ids):
182
        trees = list(tree.branch.repository.revision_trees(revision_ids))
183
        for tree in trees:
184
            tree.lock_read()
185
            self.addCleanup(tree.unlock)
186
        return trees
187
188
    def test_last_modified_revision_after_commit_root_unchanged(self):
189
        # commiting without changing the root does not change the 
190
        # last modified except on non-rich-root-repositories.
191
        tree = self.make_branch_and_tree('.')
192
        rev1 = tree.commit('')
193
        rev2 = tree.commit('')
194
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
195
        self.assertEqual(rev1, tree1.inventory.root.revision)
196
        if tree.branch.repository.supports_rich_root():
197
            self.assertEqual(rev1, tree2.inventory.root.revision)
198
        else:
199
            self.assertEqual(rev2, tree2.inventory.root.revision)
200
201
    def _add_commit_check_unchanged(self, tree, name):
202
        tree.add([name], [name + 'id'])
203
        rev1 = tree.commit('')
204
        rev2 = tree.commit('')
205
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
206
        self.assertEqual(rev1, tree1.inventory[name + 'id'].revision)
207
        self.assertEqual(rev1, tree2.inventory[name + 'id'].revision)
208
        self.assertFileAncestry([rev1], tree, name)
209
210
    def test_last_modified_revision_after_commit_dir_unchanged(self):
211
        # committing without changing a dir does not change the last modified.
212
        tree = self.make_branch_and_tree('.')
213
        self.build_tree(['dir/'])
214
        self._add_commit_check_unchanged(tree, 'dir')
215
216
    def test_last_modified_revision_after_commit_dir_contents_unchanged(self):
217
        # committing without changing a dir does not change the last modified
218
        # of the dir even the dirs contents are changed.
219
        tree = self.make_branch_and_tree('.')
220
        self.build_tree(['dir/'])
221
        tree.add(['dir'], ['dirid'])
222
        rev1 = tree.commit('')
223
        self.build_tree(['dir/content'])
224
        tree.add(['dir/content'], ['contentid'])
225
        rev2 = tree.commit('')
226
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
227
        self.assertEqual(rev1, tree1.inventory['dirid'].revision)
228
        self.assertEqual(rev1, tree2.inventory['dirid'].revision)
229
        self.assertFileAncestry([rev1], tree, 'dir')
230
231
    def test_last_modified_revision_after_commit_file_unchanged(self):
232
        # committing without changing a file does not change the last modified.
233
        tree = self.make_branch_and_tree('.')
234
        self.build_tree(['file'])
235
        self._add_commit_check_unchanged(tree, 'file')
236
237
    def test_last_modified_revision_after_commit_link_unchanged(self):
238
        # committing without changing a link does not change the last modified.
239
        self.requireFeature(tests.SymlinkFeature)
240
        tree = self.make_branch_and_tree('.')
241
        os.symlink('target', 'link')
242
        self._add_commit_check_unchanged(tree, 'link')
243
244
    def _add_commit_renamed_check_changed(self, tree, name):
245
        def rename():
246
            tree.rename_one(name, 'new_' + name)
247
        self._add_commit_change_check_changed(tree, name, rename)
248
249
    def test_last_modified_revision_after_rename_dir_changes(self):
250
        # renaming a dir changes the last modified.
251
        tree = self.make_branch_and_tree('.')
252
        self.build_tree(['dir/'])
253
        self._add_commit_renamed_check_changed(tree, 'dir')
254
255
    def test_last_modified_revision_after_rename_file_changes(self):
256
        # renaming a file changes the last modified.
257
        tree = self.make_branch_and_tree('.')
258
        self.build_tree(['file'])
259
        self._add_commit_renamed_check_changed(tree, 'file')
260
261
    def test_last_modified_revision_after_rename_link_changes(self):
262
        # renaming a link changes the last modified.
263
        self.requireFeature(tests.SymlinkFeature)
264
        tree = self.make_branch_and_tree('.')
265
        os.symlink('target', 'link')
266
        self._add_commit_renamed_check_changed(tree, 'link')
267
268
    def _add_commit_reparent_check_changed(self, tree, name):
269
        self.build_tree(['newparent/'])
270
        tree.add(['newparent'])
271
        def reparent():
272
            tree.rename_one(name, 'newparent/new_' + name)
273
        self._add_commit_change_check_changed(tree, name, reparent)
274
275
    def test_last_modified_revision_after_reparent_dir_changes(self):
276
        # reparenting a dir changes the last modified.
277
        tree = self.make_branch_and_tree('.')
278
        self.build_tree(['dir/'])
279
        self._add_commit_reparent_check_changed(tree, 'dir')
280
281
    def test_last_modified_revision_after_reparent_file_changes(self):
282
        # reparenting a file changes the last modified.
283
        tree = self.make_branch_and_tree('.')
284
        self.build_tree(['file'])
285
        self._add_commit_reparent_check_changed(tree, 'file')
286
287
    def test_last_modified_revision_after_reparent_link_changes(self):
288
        # reparenting a link changes the last modified.
289
        self.requireFeature(tests.SymlinkFeature)
290
        tree = self.make_branch_and_tree('.')
291
        os.symlink('target', 'link')
292
        self._add_commit_reparent_check_changed(tree, 'link')
293
294
    def _add_commit_change_check_changed(self, tree, name, changer):
295
        tree.add([name], [name + 'id'])
296
        rev1 = tree.commit('')
297
        changer()
298
        rev2 = tree.commit('')
299
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
300
        self.assertEqual(rev1, tree1.inventory[name + 'id'].revision)
301
        self.assertEqual(rev2, tree2.inventory[name + 'id'].revision)
302
        self.assertFileAncestry([rev1, rev2], tree, name)
303
304
    def assertFileAncestry(self, ancestry, tree, name, alt_ancestry=None):
305
        # all the changes that have occured should be in the ancestry
306
        # (closest to a public per-file graph API we have today)
307
        tree.lock_read()
308
        self.addCleanup(tree.unlock)
309
        vw = tree.branch.repository.weave_store.get_weave(name + 'id',
310
            tree.branch.repository.get_transaction())
311
        result = vw.get_ancestry([ancestry[-1]])
312
        if alt_ancestry is None:
313
            self.assertEqual(ancestry, result)
314
        else:
315
            self.assertSubset([tuple(result)],
316
                [tuple(ancestry), tuple(alt_ancestry)])
317
318
    def test_last_modified_revision_after_content_file_changes(self):
319
        # altering a file changes the last modified.
320
        tree = self.make_branch_and_tree('.')
321
        self.build_tree(['file'])
322
        def change_file():
323
            tree.put_file_bytes_non_atomic('fileid', 'new content')
324
        self._add_commit_change_check_changed(tree, 'file', change_file)
325
326
    def test_last_modified_revision_after_content_link_changes(self):
327
        # changing a link changes the last modified.
328
        self.requireFeature(tests.SymlinkFeature)
329
        tree = self.make_branch_and_tree('.')
330
        os.symlink('target', 'link')
331
        def change_link():
332
            os.unlink('link')
333
            os.symlink('newtarget', 'link')
334
        self._add_commit_change_check_changed(tree, 'link', change_link)
335
336
    def _commit_sprout(self, tree, name):
337
        tree.add([name], [name + 'id'])
338
        rev_id = tree.commit('')
339
        return rev_id, tree.bzrdir.sprout('t2').open_workingtree()
340
341
    def _rename_in_tree(self, tree, name):
342
        tree.rename_one(name, 'new_' + name)
343
        return tree.commit('')
344
345
    def _commit_sprout_rename_merge(self, tree1, name):
346
        rev1, tree2 = self._commit_sprout(tree1, name)
347
        # change both sides equally
348
        rev2 = self._rename_in_tree(tree1, name)
349
        rev3 = self._rename_in_tree(tree2, name)
350
        tree1.merge_from_branch(tree2.branch)
351
        rev4 = tree1.commit('')
352
        tree3, = self._get_revtrees(tree1, [rev4])
353
        self.assertEqual(rev4, tree3.inventory[name + 'id'].revision)
2776.4.2 by Robert Collins
nuke _read_tree_state and snapshot from inventory, moving responsibility into the commit builder.
354
        # TODO: change this to an assertFileGraph call to check the
355
        # parent order of rev4: it should be rev2, rev3
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
356
        self.assertFileAncestry([rev1, rev2, rev3, rev4], tree1, name,
357
            [rev1, rev3, rev2, rev4])
358
359
    def test_last_modified_revision_after_merge_dir_changes(self):
360
        # merge a dir changes the last modified.
361
        tree1 = self.make_branch_and_tree('t1')
362
        self.build_tree(['t1/dir/'])
363
        self._commit_sprout_rename_merge(tree1, 'dir')
364
365
    def test_last_modified_revision_after_merge_file_changes(self):
366
        # merge a file changes the last modified.
367
        tree1 = self.make_branch_and_tree('t1')
368
        self.build_tree(['t1/file'])
369
        self._commit_sprout_rename_merge(tree1, 'file')
370
371
    def test_last_modified_revision_after_merge_link_changes(self):
372
        # merge a link changes the last modified.
373
        self.requireFeature(tests.SymlinkFeature)
374
        tree1 = self.make_branch_and_tree('t1')
375
        os.symlink('target', 't1/link')
376
        self._commit_sprout_rename_merge(tree1, 'link')
377
378
    def _commit_sprout_rename_merge_converged(self, tree1, name):
379
        rev1, tree2 = self._commit_sprout(tree1, name)
380
        # change on the other side to merge back
381
        rev2 = self._rename_in_tree(tree2, name)
382
        tree1.merge_from_branch(tree2.branch)
383
        rev3 = tree1.commit('')
384
        tree3, = self._get_revtrees(tree1, [rev2])
385
        self.assertEqual(rev2, tree3.inventory[name + 'id'].revision)
386
        self.assertFileAncestry([rev1, rev2], tree1, name)
387
388
    def test_last_modified_revision_after_converged_merge_dir_changes(self):
389
        # merge a dir changes the last modified.
390
        tree1 = self.make_branch_and_tree('t1')
391
        self.build_tree(['t1/dir/'])
392
        self._commit_sprout_rename_merge_converged(tree1, 'dir')
393
394
    def test_last_modified_revision_after_converged_merge_file_changes(self):
395
        # merge a file changes the last modified.
396
        tree1 = self.make_branch_and_tree('t1')
397
        self.build_tree(['t1/file'])
398
        self._commit_sprout_rename_merge_converged(tree1, 'file')
399
400
    def test_last_modified_revision_after_converged_merge_link_changes(self):
401
        # merge a link changes the last modified.
402
        self.requireFeature(tests.SymlinkFeature)
403
        tree1 = self.make_branch_and_tree('t1')
404
        os.symlink('target', 't1/link')
405
        self._commit_sprout_rename_merge_converged(tree1, 'link')
406
407
    def make_dir(self, name):
408
        self.build_tree([name + '/'])
409
410
    def make_file(self, name):
411
        self.build_tree([name])
412
413
    def make_link(self, name):
414
        self.requireFeature(tests.SymlinkFeature)
415
        os.symlink('target', name)
416
417
    def _check_kind_change(self, make_before, make_after):
418
        tree = self.make_branch_and_tree('.')
419
        path = 'name'
420
        make_before(path)
421
        def change_kind():
422
            try:
423
                os.unlink(path)
424
            except OSError, e:
425
                if e.errno != EISDIR:
426
                    raise
427
                os.rmdir(path)
428
            make_after(path)
429
        self._add_commit_change_check_changed(tree, path, change_kind)
430
431
    def test_last_modified_dir_file(self):
432
        self._check_kind_change(self.make_dir, self.make_file)
433
434
    def test_last_modified_dir_link(self):
435
        self._check_kind_change(self.make_dir, self.make_link)
436
437
    def test_last_modified_link_file(self):
438
        self._check_kind_change(self.make_link, self.make_file)
439
440
    def test_last_modified_link_dir(self):
441
        self._check_kind_change(self.make_link, self.make_dir)
442
443
    def test_last_modified_file_dir(self):
444
        self._check_kind_change(self.make_file, self.make_dir)
445
446
    def test_last_modified_file_link(self):
447
        self._check_kind_change(self.make_file, self.make_link)