Merge ~cjwatson/launchpad:fix-lfa-encoding into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 87772b732086212139491ad12d680f04e059aab4
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:fix-lfa-encoding
Merge into: launchpad:master
Diff against target: 93 lines (+62/-5)
2 files modified
lib/lp/services/librarian/tests/test_utils.py (+61/-4)
lib/lp/services/librarian/utils.py (+1/-1)
Reviewer Review Type Date Requested Status
Cristian Gonzalez (community) Approve
Review via email: mp+407468@code.launchpad.net

Commit message

Fix position tracking in EncodableLibraryFileAlias

Description of the change

Python's `len()` requires that `__len__` returns a value greater than or equal to 0. `EncodableLibraryFileAlias` violated this in the case where a caller passed an explicit length to its `read` method which was greater than the number of bytes remaining. In this case, increase the position only up to the end of the file, not past it.

To post a comment you must log in.
Revision history for this message
Cristian Gonzalez (cristiangsp) wrote :

Looks good!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/services/librarian/tests/test_utils.py b/lib/lp/services/librarian/tests/test_utils.py
2index a7059b9..79b2f74 100644
3--- a/lib/lp/services/librarian/tests/test_utils.py
4+++ b/lib/lp/services/librarian/tests/test_utils.py
5@@ -1,12 +1,20 @@
6-# Copyright 2009 Canonical Ltd. This software is licensed under the
7+# Copyright 2009-2021 Canonical Ltd. This software is licensed under the
8 # GNU Affero General Public License version 3 (see the file LICENSE).
9
10-import unittest
11+import transaction
12
13-from lp.services.librarian.utils import guess_librarian_encoding
14+from lp.services.librarian.utils import (
15+ EncodableLibraryFileAlias,
16+ guess_librarian_encoding,
17+ )
18+from lp.testing import (
19+ TestCase,
20+ TestCaseWithFactory,
21+ )
22+from lp.testing.layers import LaunchpadZopelessLayer
23
24
25-class LibrarianUtils(unittest.TestCase):
26+class LibrarianUtils(TestCase):
27 """Librarian utilities functions."""
28
29 def test_guess_librarian_encoding(self):
30@@ -39,3 +47,52 @@ class LibrarianUtils(unittest.TestCase):
31 'foo.diff.gz', 'will_be_overridden')
32 self.assertEqual(encoding, 'gzip')
33 self.assertEqual(mimetype, 'text/plain')
34+
35+
36+class TestEncodableLibraryFileAlias(TestCaseWithFactory):
37+
38+ layer = LaunchpadZopelessLayer
39+
40+ def test_read_all(self):
41+ lfa = self.factory.makeLibraryFileAlias(content=b'abcdefgh')
42+ transaction.commit()
43+ lfa.open()
44+ try:
45+ encodable_lfa = EncodableLibraryFileAlias(lfa)
46+ self.assertEqual(8, len(encodable_lfa))
47+ self.assertEqual(b'abcdefgh', encodable_lfa.read())
48+ self.assertEqual(0, len(encodable_lfa))
49+ finally:
50+ lfa.close()
51+
52+ def test_read_some(self):
53+ lfa = self.factory.makeLibraryFileAlias(content=b'abcdefgh')
54+ transaction.commit()
55+ lfa.open()
56+ try:
57+ encodable_lfa = EncodableLibraryFileAlias(lfa)
58+ self.assertEqual(8, len(encodable_lfa))
59+ self.assertEqual(b'a', encodable_lfa.read(1))
60+ self.assertEqual(7, len(encodable_lfa))
61+ self.assertEqual(b'bc', encodable_lfa.read(2))
62+ self.assertEqual(5, len(encodable_lfa))
63+ self.assertEqual(b'defgh', encodable_lfa.read())
64+ self.assertEqual(0, len(encodable_lfa))
65+ finally:
66+ lfa.close()
67+
68+ def test_read_past_end(self):
69+ lfa = self.factory.makeLibraryFileAlias(content=b'abcdefgh')
70+ transaction.commit()
71+ lfa.open()
72+ try:
73+ encodable_lfa = EncodableLibraryFileAlias(lfa)
74+ self.assertEqual(8, len(encodable_lfa))
75+ self.assertEqual(b'a', encodable_lfa.read(1))
76+ self.assertEqual(7, len(encodable_lfa))
77+ self.assertEqual(b'bcdefgh', encodable_lfa.read(8))
78+ self.assertEqual(0, len(encodable_lfa))
79+ self.assertEqual(b'', encodable_lfa.read(8))
80+ self.assertEqual(0, len(encodable_lfa))
81+ finally:
82+ lfa.close()
83diff --git a/lib/lp/services/librarian/utils.py b/lib/lp/services/librarian/utils.py
84index bc0895b..a8423e0 100644
85--- a/lib/lp/services/librarian/utils.py
86+++ b/lib/lp/services/librarian/utils.py
87@@ -93,5 +93,5 @@ class EncodableLibraryFileAlias:
88 if chunksize is None:
89 self.position = self.lfa.content.filesize
90 else:
91- self.position += length
92+ self.position += len(data)
93 return data

Subscribers

People subscribed via source and target branches

to status/vote changes: