From cf0b6c03df5b014e8c21ffcb0fe92f58e11c7ae3 Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Sun, 17 May 2015 23:51:37 -0700 Subject: Properly test raw writes in Python 3 Previously we were trying to test writing bytes in Python 3 using only native (unicode) string objects. That doesn't test what we thought we were testing. Change-Id: I10a0a38143d7f7d850ab9a7005ad87f5d314c375 --- tests/unit/test_multithreading.py | 27 ++++++++++----------------- tests/unit/utils.py | 25 ++++++++++++------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/tests/unit/test_multithreading.py b/tests/unit/test_multithreading.py index 6597793..42abbbf 100644 --- a/tests/unit/test_multithreading.py +++ b/tests/unit/test_multithreading.py @@ -12,7 +12,6 @@ # implied. # See the License for the specific language governing permissions and # limitations under the License. - import sys import testtools import threading @@ -206,10 +205,12 @@ class TestOutputManager(testtools.TestCase): u'some raw bytes: \u062A\u062A'.encode('utf-8')) thread_manager.print_items([ - ('key', u'value'), - ('object', 'O\xcc\x88bject') + ('key', 'value'), + ('object', u'O\u0308bject'), ]) + thread_manager.print_raw(b'\xffugly\xffraw') + # Now we have a thread for error printing and a thread for # normal print messages self.assertEqual(starting_thread_count + 2, @@ -220,31 +221,23 @@ class TestOutputManager(testtools.TestCase): if six.PY3: over_the = "over the '\u062a\u062a'\n" - # The CaptureStreamBuffer just encodes all bytes written to it by - # mapping chr over the byte string to produce a str. - raw_bytes = ''.join( - map(chr, u'some raw bytes: \u062A\u062A'.encode('utf-8')) - ) else: over_the = "over the u'\\u062a\\u062a'\n" # We write to the CaptureStream so no decoding is performed - raw_bytes = 'some raw bytes: \xd8\xaa\xd8\xaa' self.assertEqual(''.join([ 'one-argument\n', 'one fish, 88 fish\n', 'some\n', 'where\n', - over_the, raw_bytes, + over_the, + u'some raw bytes: \u062a\u062a', ' key: value\n', - ' object: O\xcc\x88bject\n' - ]), out_stream.getvalue()) + u' object: O\u0308bject\n' + ]).encode('utf8') + b'\xffugly\xffraw', out_stream.getvalue()) - first_item = u'I have 99 problems, but a \u062A\u062A is not one\n' - if six.PY2: - first_item = first_item.encode('utf8') self.assertEqual(''.join([ - first_item, + u'I have 99 problems, but a \u062A\u062A is not one\n', 'one-error-argument\n', 'Sometimes\n', '3.1% just\n', 'does not\n', 'work!\n' - ]), err_stream.getvalue()) + ]), err_stream.getvalue().decode('utf8')) self.assertEqual(3, thread_manager.error_count) diff --git a/tests/unit/utils.py b/tests/unit/utils.py index 955296e..aced173 100644 --- a/tests/unit/utils.py +++ b/tests/unit/utils.py @@ -381,28 +381,27 @@ class MockHttpTest(testtools.TestCase): reload_module(c) -class CaptureStreamBuffer(object): +class CaptureStreamPrinter(object): """ - CaptureStreamBuffer is used for testing raw byte writing for PY3. Anything - written here is decoded as utf-8 and written to the parent CaptureStream + CaptureStreamPrinter is used for testing unicode writing for PY3. Anything + written here is encoded as utf-8 and written to the parent CaptureStream """ def __init__(self, captured_stream): self._captured_stream = captured_stream - def write(self, bytes_data): + def write(self, data): # No encoding, just convert the raw bytes into a str for testing # The below call also validates that we have a byte string. self._captured_stream.write( - ''.join(map(chr, bytes_data)) - ) + data if isinstance(data, six.binary_type) else data.encode('utf8')) class CaptureStream(object): def __init__(self, stream): self.stream = stream - self._capture = six.StringIO() - self._buffer = CaptureStreamBuffer(self) + self._buffer = six.BytesIO() + self._capture = CaptureStreamPrinter(self._buffer) self.streams = [self._capture] @property @@ -425,11 +424,11 @@ class CaptureStream(object): stream.writelines(*args, **kwargs) def getvalue(self): - return self._capture.getvalue() + return self._buffer.getvalue() def clear(self): - self._capture.truncate(0) - self._capture.seek(0) + self._buffer.truncate(0) + self._buffer.seek(0) class CaptureOutput(object): @@ -467,11 +466,11 @@ class CaptureOutput(object): @property def out(self): - return self._out.getvalue() + return self._out.getvalue().decode('utf8') @property def err(self): - return self._err.getvalue() + return self._err.getvalue().decode('utf8') def clear(self): self._out.clear() -- cgit v1.2.1