Commit e9d29e09f2742aa37f083d4169a19384fa91e062

Authored by Christian Herdtweck
1 parent 5bccb6aa

tests: test common.uopen

tests/common/test_encoding_handler.py
1 """Test common.ensure_stdout_handles_unicode""" 1 """Test common.ensure_stdout_handles_unicode"""
2 2
  3 +from __future__ import print_function
  4 +
3 import unittest 5 import unittest
4 import sys 6 import sys
5 -from subprocess import check_call 7 +from subprocess import check_call, CalledProcessError
6 from tempfile import mkstemp 8 from tempfile import mkstemp
7 import os 9 import os
8 from os.path import isfile 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 class TestEncodingHandler(unittest.TestCase): 44 class TestEncodingHandler(unittest.TestCase):
12 """Tests replacing stdout encoding in various scenarios""" 45 """Tests replacing stdout encoding in various scenarios"""
13 46
14 - def test_base(self): 47 + def test_print(self):
15 """Test regular unicode output not raise error""" 48 """Test regular unicode output not raise error"""
16 check_call('{python} {this_file} print'.format(python=sys.executable, 49 check_call('{python} {this_file} print'.format(python=sys.executable,
17 this_file=__file__), 50 this_file=__file__),
18 shell=True) 51 shell=True)
19 52
20 - def test_redirect(self): 53 + def test_print_redirect(self):
21 """ 54 """
22 Test redirection of unicode output to files does not raise error 55 Test redirection of unicode output to files does not raise error
23 56
24 TODO: test this on non-linux OSs 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 check_call('{python} {this_file} print > {tmp_file}' 60 check_call('{python} {this_file} print > {tmp_file}'
31 .format(python=sys.executable, this_file=__file__, 61 .format(python=sys.executable, this_file=__file__,
32 tmp_file=tmp_file), 62 tmp_file=tmp_file),
33 shell=True) 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 @unittest.skipIf(not sys.platform.startswith('linux'), 65 @unittest.skipIf(not sys.platform.startswith('linux'),
43 'Only tested on linux sofar') 66 'Only tested on linux sofar')
44 - def test_no_lang(self): 67 + def test_print_no_lang(self):
45 """ 68 """
46 Test redirection of unicode output to files does not raise error 69 Test redirection of unicode output to files does not raise error
47 70
@@ -51,28 +74,133 @@ class TestEncodingHandler(unittest.TestCase): @@ -51,28 +74,133 @@ class TestEncodingHandler(unittest.TestCase):
51 .format(python=sys.executable, this_file=__file__), 74 .format(python=sys.executable, this_file=__file__),
52 shell=True) 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 def run_print(): 169 def run_print():
55 """This is called from test_read* tests as script. Prints & logs unicode""" 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 # tests call this file as script 183 # tests call this file as script
68 if __name__ == '__main__': 184 if __name__ == '__main__':
69 if len(sys.argv) < 2: 185 if len(sys.argv) < 2:
70 sys.exit(unittest.main()) 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 if sys.argv[1] == 'print': 194 if sys.argv[1] == 'print':
72 if len(sys.argv) > 2: 195 if len(sys.argv) > 2:
73 print('Expect no arg for "print"', file=sys.stderr) 196 print('Expect no arg for "print"', file=sys.stderr)
74 sys.exit(2) 197 sys.exit(2)
75 sys.exit(run_print()) 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 else: 204 else:
77 print('Unexpected argument: {}'.format(sys.argv[1]), file=sys.stderr) 205 print('Unexpected argument: {}'.format(sys.argv[1]), file=sys.stderr)
78 sys.exit(2) 206 sys.exit(2)