diff --git a/pymemcache/client.py b/pymemcache/client.py index be37924..972add2 100644 --- a/pymemcache/client.py +++ b/pymemcache/client.py @@ -751,18 +751,20 @@ def _readline(sock, buf): last_char = '' while True: - idx = buf.find('\r\n') # We're reading in chunks, so "\r\n" could appear in one chunk, # or across the boundary of two chunks, so we check for both # cases. - if idx != -1: - before, sep, after = buf.partition("\r\n") - chunks.append(before) - return after, ''.join(chunks) - elif last_char == '\r' and buf[0] == '\n': + + # This case must appear first, since the buffer could have + # later \r\n characters in it and we want to get the first \r\n. + if last_char == '\r' and buf[0] == '\n': # Strip the last character from the last chunk. chunks[-1] = chunks[-1][:-1] return buf[1:], ''.join(chunks) + elif buf.find('\r\n') != -1: + before, sep, after = buf.partition("\r\n") + chunks.append(before) + return after, ''.join(chunks) if buf: chunks.append(buf) diff --git a/pymemcache/test/test_client.py b/pymemcache/test/test_client.py index 5da74c9..de4de2e 100644 --- a/pymemcache/test/test_client.py +++ b/pymemcache/test/test_client.py @@ -237,12 +237,58 @@ def test_get_many_all_found(): tools.assert_equal(result, {'key1': 'value1', 'key2': 'value2'}) -def test_get_many_cr_nl_boundary_issue(): +def test_cr_nl_boundaries(): client = Client(None) - client.sock = MockSocket(['VALUE key1 0 6\r', '\nvalue1\r', '\n', - 'VALUE key2 0 6\r', '\nvalue2', '\r\nEND\r\n']) + client.sock = MockSocket(['VALUE key1 0 6\r', + '\nvalue1\r\n' + 'VALUE key2 0 6\r\n', + 'value2\r\n' + 'END\r\n']) result = client.get_many(['key1', 'key2']) - tools.assert_equal(result, {'key1': 'value1', 'key2': 'value2'}) + tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'}) + + client.sock = MockSocket(['VALUE key1 0 6\r\n', + 'value1\r', + '\nVALUE key2 0 6\r\n', + 'value2\r\n', + 'END\r\n']) + result = client.get_many(['key1', 'key2']) + tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'}) + + client.sock = MockSocket(['VALUE key1 0 6\r\n', + 'value1\r\n', + 'VALUE key2 0 6\r', + '\nvalue2\r\n', + 'END\r\n']) + result = client.get_many(['key1', 'key2']) + tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'}) + + + client.sock = MockSocket(['VALUE key1 0 6\r\n', + 'value1\r\n', + 'VALUE key2 0 6\r\n', + 'value2\r', + '\nEND\r\n']) + result = client.get_many(['key1', 'key2']) + tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'}) + + client.sock = MockSocket(['VALUE key1 0 6\r\n', + 'value1\r\n', + 'VALUE key2 0 6\r\n', + 'value2\r\n', + 'END\r', + '\n']) + result = client.get_many(['key1', 'key2']) + tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'}) + + client.sock = MockSocket(['VALUE key1 0 6\r', + '\nvalue1\r', + '\nVALUE key2 0 6\r', + '\nvalue2\r', + '\nEND\r', + '\n']) + result = client.get_many(['key1', 'key2']) + tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'}) def test_get_unknown_error(): diff --git a/setup.py b/setup.py index f9abf2a..5c1fd77 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import setup, find_packages setup( name = 'pymemcache', - version = '0.8', + version = '0.9', author = 'Charles Gordon', author_email = 'charles@pinterest.com', packages = find_packages(),