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
diff --git a/lib/lp/services/librarian/tests/test_utils.py b/lib/lp/services/librarian/tests/test_utils.py
index a7059b9..79b2f74 100644
--- a/lib/lp/services/librarian/tests/test_utils.py
+++ b/lib/lp/services/librarian/tests/test_utils.py
@@ -1,12 +1,20 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009-2021 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4import unittest4import transaction
55
6from lp.services.librarian.utils import guess_librarian_encoding6from lp.services.librarian.utils import (
7 EncodableLibraryFileAlias,
8 guess_librarian_encoding,
9 )
10from lp.testing import (
11 TestCase,
12 TestCaseWithFactory,
13 )
14from lp.testing.layers import LaunchpadZopelessLayer
715
816
9class LibrarianUtils(unittest.TestCase):17class LibrarianUtils(TestCase):
10 """Librarian utilities functions."""18 """Librarian utilities functions."""
1119
12 def test_guess_librarian_encoding(self):20 def test_guess_librarian_encoding(self):
@@ -39,3 +47,52 @@ class LibrarianUtils(unittest.TestCase):
39 'foo.diff.gz', 'will_be_overridden')47 'foo.diff.gz', 'will_be_overridden')
40 self.assertEqual(encoding, 'gzip')48 self.assertEqual(encoding, 'gzip')
41 self.assertEqual(mimetype, 'text/plain')49 self.assertEqual(mimetype, 'text/plain')
50
51
52class TestEncodableLibraryFileAlias(TestCaseWithFactory):
53
54 layer = LaunchpadZopelessLayer
55
56 def test_read_all(self):
57 lfa = self.factory.makeLibraryFileAlias(content=b'abcdefgh')
58 transaction.commit()
59 lfa.open()
60 try:
61 encodable_lfa = EncodableLibraryFileAlias(lfa)
62 self.assertEqual(8, len(encodable_lfa))
63 self.assertEqual(b'abcdefgh', encodable_lfa.read())
64 self.assertEqual(0, len(encodable_lfa))
65 finally:
66 lfa.close()
67
68 def test_read_some(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'bc', encodable_lfa.read(2))
78 self.assertEqual(5, len(encodable_lfa))
79 self.assertEqual(b'defgh', encodable_lfa.read())
80 self.assertEqual(0, len(encodable_lfa))
81 finally:
82 lfa.close()
83
84 def test_read_past_end(self):
85 lfa = self.factory.makeLibraryFileAlias(content=b'abcdefgh')
86 transaction.commit()
87 lfa.open()
88 try:
89 encodable_lfa = EncodableLibraryFileAlias(lfa)
90 self.assertEqual(8, len(encodable_lfa))
91 self.assertEqual(b'a', encodable_lfa.read(1))
92 self.assertEqual(7, len(encodable_lfa))
93 self.assertEqual(b'bcdefgh', encodable_lfa.read(8))
94 self.assertEqual(0, len(encodable_lfa))
95 self.assertEqual(b'', encodable_lfa.read(8))
96 self.assertEqual(0, len(encodable_lfa))
97 finally:
98 lfa.close()
diff --git a/lib/lp/services/librarian/utils.py b/lib/lp/services/librarian/utils.py
index bc0895b..a8423e0 100644
--- a/lib/lp/services/librarian/utils.py
+++ b/lib/lp/services/librarian/utils.py
@@ -93,5 +93,5 @@ class EncodableLibraryFileAlias:
93 if chunksize is None:93 if chunksize is None:
94 self.position = self.lfa.content.filesize94 self.position = self.lfa.content.filesize
95 else:95 else:
96 self.position += length96 self.position += len(data)
97 return data97 return data

Subscribers

People subscribed via source and target branches

to status/vote changes: