Merge lp:~jameinel/bzr/2.3-per-transport-tests into lp:bzr

Proposed by John A Meinel
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: no longer in the source branch.
Merged at revision: 5604
Proposed branch: lp:~jameinel/bzr/2.3-per-transport-tests
Merge into: lp:bzr
Diff against target: 72 lines (+17/-6)
2 files modified
bzrlib/tests/per_transport.py (+10/-6)
doc/en/release-notes/bzr-2.3.txt (+7/-0)
To merge this branch: bzr merge lp:~jameinel/bzr/2.3-per-transport-tests
Reviewer Review Type Date Requested Status
Martin Packman (community) Approve
Review via email: mp+46047@code.launchpad.net

Commit message

Use Transport.get_bytes() instead of Transport.get().read() in the test suite.

Description of the change

http://babune.ladeuil.net:24842/job/selftest-windows/lastCompletedBuild/testReport/bzrlib.tests.per_transport/TransportTests/test_put_bytes_SFTPTransport_SFTPAbsoluteServer_/

I think this failure is just a race condition, where the server/etc is still holding the file open, and then we are trying to write over top of it.

I *hope* the issue is that .get().read() is not very atomic and quick at closing its file handle. So I switched to .get_bytes() which should be a bit better at knowing that it can close the handle immediately.

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

Code changes all look right to me, am not completely clear on this hunk though:

             self.assertEqual('b', t.get_bytes('foo'))
- self.assertEqual('b', t.get('foo').read())
+ f = t.get('foo')
+ try:
+ self.assertEqual('b', f.read())
+ finally:
+ f.close()

What's the intended effect there, that's different from two get_bytes calls or one get and two reads?

I'm not sure if this'll fix the random failures, but vila also suspects this as a potential issue in bug 681047. I'd assumed refcounts would be doing the right thing here anyway, but jam teaches me paramiko does slightly different things in __del__ from a normal close.

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

that is testing that the t.get() api understands when a file has been mutated via the write_stream api.

I did want to make sure that both .get() and .get_bytes() were updated to be aware of writing from a different method.

*many* of the transports implement get_bytes() in terms of get() or get() in terms of get_bytes() but there is no guarantee that they do so.

So I felt it was still reasonable to do a separate get + read + close.

I do feel like most of the random failures you would see should be fixed by:
8 - """Check that transport.get(relpath).read() == content."""
9 - self.assertEqualDiff(content, transport.get(relpath).read())
10 + """Check that transport.get_bytes(relpath) == content."""
11 + self.assertEqualDiff(content, transport.get_bytes(relpath))

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

sent to pqm by email

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

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/tests/per_transport.py'
2--- bzrlib/tests/per_transport.py 2011-01-10 22:20:12 +0000
3+++ bzrlib/tests/per_transport.py 2011-01-13 01:04:35 +0000
4@@ -101,8 +101,8 @@
5 self.overrideEnv('BZR_NO_SMART_VFS', None)
6
7 def check_transport_contents(self, content, transport, relpath):
8- """Check that transport.get(relpath).read() == content."""
9- self.assertEqualDiff(content, transport.get(relpath).read())
10+ """Check that transport.get_bytes(relpath) == content."""
11+ self.assertEqualDiff(content, transport.get_bytes(relpath))
12
13 def test_ensure_base_missing(self):
14 """.ensure_base() should create the directory if it doesn't exist"""
15@@ -256,7 +256,7 @@
16 handle = t.open_write_stream('foo')
17 try:
18 handle.write('b')
19- self.assertEqual('b', t.get('foo').read())
20+ self.assertEqual('b', t.get_bytes('foo'))
21 finally:
22 handle.close()
23
24@@ -268,7 +268,11 @@
25 try:
26 handle.write('b')
27 self.assertEqual('b', t.get_bytes('foo'))
28- self.assertEqual('b', t.get('foo').read())
29+ f = t.get('foo')
30+ try:
31+ self.assertEqual('b', f.read())
32+ finally:
33+ f.close()
34 finally:
35 handle.close()
36
37@@ -640,7 +644,7 @@
38 self.build_tree(files, transport=transport_from)
39 self.assertEqual(4, transport_from.copy_to(files, transport_to))
40 for f in files:
41- self.check_transport_contents(transport_to.get(f).read(),
42+ self.check_transport_contents(transport_to.get_bytes(f),
43 transport_from, f)
44
45 t = self.get_transport()
46@@ -669,7 +673,7 @@
47 files = ['a', 'b', 'c', 'd']
48 t.copy_to(iter(files), temp_transport)
49 for f in files:
50- self.check_transport_contents(temp_transport.get(f).read(),
51+ self.check_transport_contents(temp_transport.get_bytes(f),
52 t, f)
53 del temp_transport
54
55
56=== modified file 'doc/en/release-notes/bzr-2.3.txt'
57--- doc/en/release-notes/bzr-2.3.txt 2011-01-12 22:20:59 +0000
58+++ doc/en/release-notes/bzr-2.3.txt 2011-01-13 01:04:35 +0000
59@@ -73,6 +73,13 @@
60 trying to set the tags in the master branch. This had been broken by the
61 bug fix for bug #603395. (John Arbash Meinel, #701212)
62
63+* Per-transport tests now prefer to use ``Transport.get_bytes()`` rather
64+ than ``Transport.get().read()``. The SFTP code uses an async message to
65+ close the file handle if you let the handle die from refcounting, while
66+ it uses a synchronous message if you close it directly. This should help
67+ prevent random test suite failures from race conditions.
68+ (John Arbash Meinel, #681047)
69+
70 * Stop using ``bzrlib.tuned_gzip.GzipFile``. It is incompatible with
71 python-2.7 and was only used for Knit format repositories, which haven't
72 been recommended since 2007. The file itself will be removed in the next