Commit e9d29e09f2742aa37f083d4169a19384fa91e062

Authored by Christian Herdtweck
1 parent 5bccb6aa

tests: test common.uopen

tests/common/test_encoding_handler.py
1 1 """Test common.ensure_stdout_handles_unicode"""
2 2  
  3 +from __future__ import print_function
  4 +
3 5 import unittest
4 6 import sys
5   -from subprocess import check_call
  7 +from subprocess import check_call, CalledProcessError
6 8 from tempfile import mkstemp
7 9 import os
8 10 from os.path import isfile
  11 +from contextlib import contextmanager
  12 +
  13 +FILE_TEXT = u'The unicode check mark is \u2713.\n'
  14 +
  15 +@contextmanager
  16 +def temp_file(just_name=True):
  17 + """Context manager that creates temp file and deletes it in the end"""
  18 + tmp_descriptor = None
  19 + tmp_name = None
  20 + tmp_handle = None
  21 + try:
  22 + tmp_descriptor, tmp_name = mkstemp()
  23 +
  24 + # we create our own file handle since we want to be able to close the
  25 + # file and open it again for reading.
  26 + # We keep the os-level descriptor open so file name is still reserved
  27 + # for us
  28 + if just_name:
  29 + yield tmp_name
  30 + else:
  31 + tmp_handle = open(tmp_name, 'wb')
  32 + yield tmp_handle, tmp_name
  33 + except Exception:
  34 + raise
  35 + finally:
  36 + if tmp_descriptor is not None:
  37 + os.close(tmp_descriptor)
  38 + if tmp_handle is not None:
  39 + tmp_handle.close()
  40 + if tmp_name is not None and isfile(tmp_name):
  41 + os.unlink(tmp_name)
9 42  
10 43  
11 44 class TestEncodingHandler(unittest.TestCase):
12 45 """Tests replacing stdout encoding in various scenarios"""
13 46  
14   - def test_base(self):
  47 + def test_print(self):
15 48 """Test regular unicode output not raise error"""
16 49 check_call('{python} {this_file} print'.format(python=sys.executable,
17 50 this_file=__file__),
18 51 shell=True)
19 52  
20   - def test_redirect(self):
  53 + def test_print_redirect(self):
21 54 """
22 55 Test redirection of unicode output to files does not raise error
23 56  
24 57 TODO: test this on non-linux OSs
25 58 """
26   - tmp_handle = None
27   - tmp_name = None
28   - try:
29   - tmp_handle, tmp_name = mkstemp()
  59 + with temp_file() as tmp_file:
30 60 check_call('{python} {this_file} print > {tmp_file}'
31 61 .format(python=sys.executable, this_file=__file__,
32 62 tmp_file=tmp_file),
33 63 shell=True)
34   - except Exception:
35   - raise
36   - finally:
37   - if tmp_handle is not None:
38   - os.close(tmp_handle)
39   - if tmp_name is not None and isfile(tmp_name):
40   - os.unlink(tmp_name)
41 64  
42 65 @unittest.skipIf(not sys.platform.startswith('linux'),
43 66 'Only tested on linux sofar')
44   - def test_no_lang(self):
  67 + def test_print_no_lang(self):
45 68 """
46 69 Test redirection of unicode output to files does not raise error
47 70  
... ... @@ -51,28 +74,133 @@ class TestEncodingHandler(unittest.TestCase):
51 74 .format(python=sys.executable, this_file=__file__),
52 75 shell=True)
53 76  
  77 + def test_uopen(self):
  78 + """Test that uopen in a nice environment is ok"""
  79 + with temp_file(False) as (tmp_handle, tmp_file):
  80 + tmp_handle.write(FILE_TEXT.encode('utf8'))
  81 + tmp_handle.close()
  82 +
  83 + try:
  84 + check_call('{python} {this_file} read {tmp_file}'
  85 + .format(python=sys.executable, this_file=__file__,
  86 + tmp_file=tmp_file),
  87 + shell=True)
  88 + except CalledProcessError as cpe:
  89 + self.fail(cpe.output)
  90 +
  91 + def test_uopen_redirect(self):
  92 + """
  93 + Test redirection of unicode output to files does not raise error
  94 +
  95 + TODO: test this on non-linux OSs
  96 + """
  97 + with temp_file(False) as (tmp_handle, tmp_file):
  98 + tmp_handle.write(FILE_TEXT.encode('utf8'))
  99 + tmp_handle.close()
  100 +
  101 + with temp_file() as redirect_file:
  102 + try:
  103 + check_call(
  104 + '{python} {this_file} read {tmp_file} >{redirect_file}'
  105 + .format(python=sys.executable, this_file=__file__,
  106 + tmp_file=tmp_file, redirect_file=redirect_file),
  107 + shell=True)
  108 + except CalledProcessError as cpe:
  109 + self.fail(cpe.output)
  110 +
  111 + @unittest.skipIf(not sys.platform.startswith('linux'),
  112 + 'Only tested on linux sofar')
  113 + def test_uopen_no_lang(self):
  114 + """
  115 + Test that uopen in a C-LANG environment is ok
  116 +
  117 + TODO: Adapt this for other OSs; for win create batch script
  118 + """
  119 + with temp_file(False) as (tmp_handle, tmp_file):
  120 + tmp_handle.write(FILE_TEXT.encode('utf8'))
  121 + tmp_handle.close()
  122 +
  123 + try:
  124 + check_call('LANG=C {python} {this_file} read {tmp_file}'
  125 + .format(python=sys.executable, this_file=__file__,
  126 + tmp_file=tmp_file),
  127 + shell=True)
  128 + except CalledProcessError as cpe:
  129 + self.fail(cpe.output)
  130 +
  131 +
  132 +def run_read(filename):
  133 + """This is called from test_uopen* tests as script. Reads text, compares"""
  134 + from oletools.common import uopen
  135 + # open file
  136 + with uopen(filename, 'rt') as reader:
  137 + # a few tests
  138 + if reader.closed:
  139 + raise ValueError('handle is closed!')
  140 + if reader.name != filename:
  141 + raise ValueError('Wrong filename {}'.format(reader.name))
  142 + if reader.isatty():
  143 + raise ValueError('Reader is a tty!')
  144 + if reader.tell() != 0:
  145 + raise ValueError('Reader.tell is not 0 at beginning')
  146 +
  147 + # read text
  148 + text = reader.read()
  149 +
  150 + # a few more tests
  151 + if not reader.closed:
  152 + raise ValueError('Reader is not closed outside context')
  153 + if reader.name != filename:
  154 + raise ValueError('Wrong filename {} after context'.format(reader.name))
  155 + if reader.isatty():
  156 + raise ValueError('Reader has become a tty!')
  157 +
  158 + # compare text
  159 + if sys.version_info.major <= 2: # in python2 get encoded byte string
  160 + expect = FILE_TEXT.encode('utf8')
  161 + else: # python3: should get real unicode
  162 + expect = FILE_TEXT
  163 + if text != expect:
  164 + raise ValueError('Wrong contents: {!r} != {!r}'
  165 + .format(text, expect))
  166 + return 0
  167 +
  168 +
54 169 def run_print():
55 170 """This is called from test_read* tests as script. Prints & logs unicode"""
56   - # hack required to import common from parent dir, not system-wide one
57   - # (usually unittest seems to do that for us)
58   - from os.path import abspath, dirname, join
59   - ole_base = dirname(dirname(dirname(abspath(__file__))))
60   - sys.path.insert(0, ole_base)
  171 + from oletools.common import ensure_stdout_handles_unicode
  172 + from oletools.common.log_helper import log_helper
  173 + ensure_stdout_handles_unicode()
  174 + print(u'Check: \u2713') # print check mark
61 175  
62   - from oletools import common
63   - common.ensure_stdout_handles_unicode()
64   - print(u'\u2713') # print check mark
  176 + # check logging as well
  177 + logger = log_helper.get_or_create_silent_logger('test_encoding_handler')
  178 + log_helper.enable_logging(False, 'debug', stream=sys.stdout)
  179 + logger.info(u'Check: \u2713')
  180 + return 0
65 181  
66 182  
67 183 # tests call this file as script
68 184 if __name__ == '__main__':
69 185 if len(sys.argv) < 2:
70 186 sys.exit(unittest.main())
  187 +
  188 + # hack required to import common from parent dir, not system-wide one
  189 + # (usually unittest seems to do that for us)
  190 + from os.path import abspath, dirname, join
  191 + ole_base = dirname(dirname(dirname(abspath(__file__))))
  192 + sys.path.insert(0, ole_base)
  193 +
71 194 if sys.argv[1] == 'print':
72 195 if len(sys.argv) > 2:
73 196 print('Expect no arg for "print"', file=sys.stderr)
74 197 sys.exit(2)
75 198 sys.exit(run_print())
  199 + elif sys.argv[1] == 'read':
  200 + if len(sys.argv) != 3:
  201 + print('Expect single arg for "read"', file=sys.stderr)
  202 + sys.exit(2)
  203 + sys.exit(run_read(sys.argv[2]))
76 204 else:
77 205 print('Unexpected argument: {}'.format(sys.argv[1]), file=sys.stderr)
78 206 sys.exit(2)
... ...