1#!/usr/bin/env python3 2# -*- coding:utf-8 -*- 3# Copyright 2019 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Unittests for the utils module.""" 18 19from __future__ import print_function 20 21import datetime 22import os 23import sys 24import unittest 25 26_path = os.path.realpath(__file__ + '/../..') 27if sys.path[0] != _path: 28 sys.path.insert(0, _path) 29del _path 30 31# We have to import our local modules after the sys.path tweak. We can't use 32# relative imports because this is an executable program, not a module. 33# pylint: disable=wrong-import-position 34import rh 35import rh.utils 36 37 38class TimeDeltaStrTests(unittest.TestCase): 39 """Verify behavior of timedelta_str object.""" 40 41 def test_same(self): 42 """Check timedelta of 0 seconds.""" 43 delta = datetime.timedelta(0) 44 self.assertEqual('0.000s', rh.utils.timedelta_str(delta)) 45 46 def test_millisecondss(self): 47 """Check timedelta of milliseconds.""" 48 delta = datetime.timedelta(seconds=0.123456) 49 self.assertEqual('0.123s', rh.utils.timedelta_str(delta)) 50 51 def test_seconds(self): 52 """Check timedelta of seconds.""" 53 delta = datetime.timedelta(seconds=12.3) 54 self.assertEqual('12.300s', rh.utils.timedelta_str(delta)) 55 56 def test_minutes(self): 57 """Check timedelta of minutes.""" 58 delta = datetime.timedelta(seconds=72.3) 59 self.assertEqual('1m12.300s', rh.utils.timedelta_str(delta)) 60 61 def test_hours(self): 62 """Check timedelta of hours.""" 63 delta = datetime.timedelta(seconds=4000.3) 64 self.assertEqual('1h6m40.300s', rh.utils.timedelta_str(delta)) 65 66 67class CompletedProcessTests(unittest.TestCase): 68 """Verify behavior of CompletedProcess object.""" 69 70 def test_empty_cmdstr(self): 71 """Check cmdstr with an empty command.""" 72 result = rh.utils.CompletedProcess(args=[]) 73 self.assertEqual('', result.cmdstr) 74 75 def test_basic_cmdstr(self): 76 """Check cmdstr with a basic command command.""" 77 result = rh.utils.CompletedProcess(args=['ls', 'a b']) 78 self.assertEqual("ls 'a b'", result.cmdstr) 79 80 def test_str(self): 81 """Check str() handling.""" 82 # We don't enforce much, just that it doesn't crash. 83 result = rh.utils.CompletedProcess() 84 self.assertNotEqual('', str(result)) 85 result = rh.utils.CompletedProcess(args=[]) 86 self.assertNotEqual('', str(result)) 87 88 def test_repr(self): 89 """Check repr() handling.""" 90 # We don't enforce much, just that it doesn't crash. 91 result = rh.utils.CompletedProcess() 92 self.assertNotEqual('', repr(result)) 93 result = rh.utils.CompletedProcess(args=[]) 94 self.assertNotEqual('', repr(result)) 95 96 97class CalledProcessErrorTests(unittest.TestCase): 98 """Verify behavior of CalledProcessError object.""" 99 100 def test_basic(self): 101 """Basic test we can create a normal instance.""" 102 rh.utils.CalledProcessError(0, ['mycmd']) 103 rh.utils.CalledProcessError(1, ['mycmd'], exception=Exception('bad')) 104 105 def test_stringify(self): 106 """Check stringify() handling.""" 107 # We don't assert much so we leave flexibility in changing format. 108 err = rh.utils.CalledProcessError(0, ['mycmd']) 109 self.assertIn('mycmd', err.stringify()) 110 err = rh.utils.CalledProcessError( 111 0, ['mycmd'], exception=Exception('bad')) 112 self.assertIn('mycmd', err.stringify()) 113 114 def test_str(self): 115 """Check str() handling.""" 116 # We don't assert much so we leave flexibility in changing format. 117 err = rh.utils.CalledProcessError(0, ['mycmd']) 118 self.assertIn('mycmd', str(err)) 119 err = rh.utils.CalledProcessError( 120 0, ['mycmd'], exception=Exception('bad')) 121 self.assertIn('mycmd', str(err)) 122 123 def test_repr(self): 124 """Check repr() handling.""" 125 # We don't assert much so we leave flexibility in changing format. 126 err = rh.utils.CalledProcessError(0, ['mycmd']) 127 self.assertNotEqual('', repr(err)) 128 err = rh.utils.CalledProcessError( 129 0, ['mycmd'], exception=Exception('bad')) 130 self.assertNotEqual('', repr(err)) 131 132 133class RunCommandTests(unittest.TestCase): 134 """Verify behavior of run helper.""" 135 136 def test_basic(self): 137 """Simple basic test.""" 138 ret = rh.utils.run(['true']) 139 self.assertEqual('true', ret.cmdstr) 140 self.assertIsNone(ret.stdout) 141 self.assertIsNone(ret.stderr) 142 143 def test_stdout_capture(self): 144 """Verify output capturing works.""" 145 ret = rh.utils.run(['echo', 'hi'], redirect_stdout=True) 146 self.assertEqual('hi\n', ret.stdout) 147 self.assertIsNone(ret.stderr) 148 149 def test_stderr_capture(self): 150 """Verify stderr capturing works.""" 151 ret = rh.utils.run(['sh', '-c', 'echo hi >&2'], redirect_stderr=True) 152 self.assertIsNone(ret.stdout) 153 self.assertEqual('hi\n', ret.stderr) 154 155 def test_stdout_utf8(self): 156 """Verify reading UTF-8 data works.""" 157 ret = rh.utils.run(['printf', r'\xc3\x9f'], redirect_stdout=True) 158 self.assertEqual(u'ß', ret.stdout) 159 self.assertIsNone(ret.stderr) 160 161 def test_stdin_utf8(self): 162 """Verify writing UTF-8 data works.""" 163 ret = rh.utils.run(['cat'], redirect_stdout=True, input=u'ß') 164 self.assertEqual(u'ß', ret.stdout) 165 self.assertIsNone(ret.stderr) 166 167 168if __name__ == '__main__': 169 unittest.main() 170