Merge lp:~gz/bzr/tests_for_bug_205636 into lp:bzr

Proposed by Martin Packman
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: no longer in the source branch.
Merged at revision: 5520
Proposed branch: lp:~gz/bzr/tests_for_bug_205636
Merge into: lp:bzr
Diff against target: 60 lines (+43/-0)
1 file modified
bzrlib/tests/per_workingtree/test_smart_add.py (+43/-0)
To merge this branch: bzr merge lp:~gz/bzr/tests_for_bug_205636
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Martin Pool Approve
Review via email: mp+38673@code.launchpad.net

Description of the change

The problem of adding files in a directory that used to be a file described in bug 205636 was found to have been fixed by the bug 192859 symlink related changes. However, no tests specifically for that case were added. While making this branch, I discovered only one on my two ways of reproducing the problem has actually been fixed, but these tests can land at least.

I followed the per_workingtree placement in Martin Pool's symlink branch tests. However, I'm not sure the test_add test that fails with the older working tree formats is really valid, from the command line I only get failures down the smart_add path so perhaps add isn't expected to deal with this kind of oddness.

The remaining issue that will need fixing can be reproduced with:

    >bzr init test
    >cd test
    >echo Test>dir
    >bzr add dir
    >del dir
    >mkdir dir\dir
    >bzr add dir

(What, "bash: del: command not found"? I'm not crazy about shell tests either.)

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Looks like bug 251864 sort of covers the smart_add case that still fails.

Revision history for this message
Vincent Ladeuil (vila) wrote :

>>>>> Martin [gz] <email address hidden> writes:

<snip/>
    > The remaining issue that will need fixing can be reproduced with:

    >> bzr init test
    >> cd test
    >> echo Test>dir
    >> bzr add dir
    >> del dir
    >> mkdir dir\dir
    >> bzr add dir

    > (What, "bash: del: command not found"? I'm not crazy about shell tests either.)

Try shell-like tests then :-p

Revision history for this message
John A Meinel (jameinel) wrote :

I don't understand the need for the "reraise as Assertion" code. Why not just call "self.knonwFailure()". ?

Revision history for this message
Martin Packman (gz) wrote :

I was writing these tests to find out what triggered the bug, and when it was fixed. Using self.knownFailure means the problem code is never actually run. With self.expectFailure instead, the code *is* run, and if it starts passing (after the merge in the second rev for instance) then you get an unexpected success (but see bug 654474) instead. An expectError method could also fail if the error type changes.

With lp:~gz/bzr/smart_add_former_file_dir_251864 merged as well, this rather ugly assertion adapter code is removed as the test starts passing and it's not needed any more.

Revision history for this message
Martin Packman (gz) wrote :

> Try shell-like tests then :-p

I did, and found a bug in the error handling both there and in my own code testtools...

Revision history for this message
John A Meinel (jameinel) wrote :

63 + try:
64 + tree.smart_add(["dir"])
65 + except AttributeError, e:
66 + self.expectFailure("Adding dir raises AttributeError",
67 + self._reraise_current_error_as_assertion)

^- Looking at this, I don't see any reason why expectFailure would "run the code".

If you did:

self.expectFailure("Adding dir raises AttributeError",
  self._reraise_error_as_assertion, tree.smart_add, ['dir'])

Or something along those lines, then I could see your point. The try/except code means that you will *only* call self._reraise_current... if an exception has already triggered, and as such you always know that the code is executing, etc.

try:
 ...
except AttributeError:
  self.knownFailure(...)

is much more straightforward.

Revision history for this message
Martin Packman (gz) wrote :

Yeah, your two alternative spellings there are much clearer. I'll leave this branch unchanged for the moment though as that was a temporary hack that's going away.

Having a real expectError method would both keep the exc_info unmolested and avoid the need for try/except, but was out of scope here.

Revision history for this message
Martin Packman (gz) wrote :

I would really like some input on:

* If test_add is correct, and whether the old working tree formats should be fixed.
* If anything else should be asserted in the tests, and if so what.

Revision history for this message
Martin Pool (mbp) wrote :

> > (What, "bash: del: command not found"? I'm not crazy about shell tests
> either.)
>
> Try shell-like tests then :-p

The point being, of course, that they should rarely or never actually depend on local OS shell behaviour. rm in a shell-like test just directly deletes it.

Revision history for this message
Martin Pool (mbp) wrote :

> I would really like some input on:
>
> * If test_add is correct, and whether the old working tree formats should be
> fixed.
> * If anything else should be asserted in the tests, and if so what.

The tests look reasonable.

I would not bother fixing the old formats.

I would think about adding some additional assertions that the files within the directories are now versioned.

review: Approve
Revision history for this message
Vincent Ladeuil (vila) wrote :

Summarizing the comments:
* add assertions that 'dir' and 'dir/file' are versioned
* get rid of the re-raise if it's not needed anymore

And I'll add: avoid importing os and use the osutils equivalents. While not strictly necessary yet, we plan to make working trees fully testable in-memory via transports and 'os' calls won't work there. Limiting such calls to the minimum needed will help.

review: Approve
Revision history for this message
Martin Packman (gz) wrote :

Added some state of tree assertions, again modelled on what Martin Pool used in the bug 192859 branch. This showed the test_add test was really not doing the right thing. As it isn't what `bzr add` ends up using and no one outright said it was valid, I just removed it.

I don't get what you mean about os.remove Vincent. I'd need a transport method to avoid filesystem specificity not just osutils, and my understanding was this is not yet done as per bug 606249 and so on.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/tests/per_workingtree/test_smart_add.py'
2--- bzrlib/tests/per_workingtree/test_smart_add.py 2010-02-23 07:43:11 +0000
3+++ bzrlib/tests/per_workingtree/test_smart_add.py 2010-11-02 22:11:44 +0000
4@@ -17,6 +17,7 @@
5 """Test that we can use smart_add on all Tree implementations."""
6
7 from cStringIO import StringIO
8+import os
9 import sys
10
11 from bzrlib import (
12@@ -202,6 +203,48 @@
13 self.assertEqual(['', 'dir', 'dir/subdir', 'dir/subdir/foo'],
14 [path for path, ie in tree.iter_entries_by_dir()])
15
16+ @staticmethod
17+ def _reraise_current_error_as_assertion():
18+ _, e, tb = sys.exc_info()
19+ try:
20+ raise AssertionError, AssertionError(str(e)), tb
21+ finally:
22+ del tb
23+
24+ def test_add_dir_bug_205636(self):
25+ """Added file turning into a dir should be detected on add dir"""
26+ tree = self.make_branch_and_tree(".")
27+ self.build_tree(["dir"]) # whoops, make a file called dir
28+ tree.smart_add(["dir"])
29+ os.remove("dir")
30+ self.build_tree(["dir/", "dir/file"])
31+ # GZ 2010-10-17: Need an expectError method like expectFailure but for
32+ # execptions that are not assertions
33+ try:
34+ tree.smart_add(["dir"])
35+ except AttributeError, e:
36+ self.expectFailure("Adding dir raises AttributeError",
37+ self._reraise_current_error_as_assertion)
38+ tree.commit("Add dir contents")
39+ self.addCleanup(tree.lock_read().unlock)
40+ self.assertEqual([(u"dir", "directory"), (u"dir/file", "file")],
41+ [(t[0], t[2]) for t in tree.list_files()])
42+ self.assertFalse(list(tree.iter_changes(tree.basis_tree())))
43+
44+ def test_add_subdir_file_bug_205636(self):
45+ """Added file turning into a dir should be detected on add dir/file"""
46+ tree = self.make_branch_and_tree(".")
47+ self.build_tree(["dir"]) # whoops, make a file called dir
48+ tree.smart_add(["dir"])
49+ os.remove("dir")
50+ self.build_tree(["dir/", "dir/file"])
51+ tree.smart_add(["dir/file"])
52+ tree.commit("Add file in dir")
53+ self.addCleanup(tree.lock_read().unlock)
54+ self.assertEqual([(u"dir", "directory"), (u"dir/file", "file")],
55+ [(t[0], t[2]) for t in tree.list_files()])
56+ self.assertFalse(list(tree.iter_changes(tree.basis_tree())))
57+
58 def test_custom_ids(self):
59 sio = StringIO()
60 action = test_smart_add.AddCustomIDAction(to_file=sio,