blob: 878113d90b44750a95d1b5add3c284ae4bd054b6 [file] [log] [blame]
#!/usr/bin/env python2.7
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import errno
import os
import shutil
import subprocess
import sys
import tempfile
import unittest
from StringIO import StringIO
import test_env
from lib.host import Host
from host_fake import FakeHost
from test_case import TestCaseWithIO
""" Test the real and fake implementations of the Host.
The structure of these tests is organized into 5 classes:
NonHermeticTestCase HostTestCase HermeticTestCase
^ ^ ^ ^
| | | |
+-HostTest-+ +-FakeHostTest-+
NonHermeticTestCase is a TestCase that provides real-system utility functions.
HermeticTestCase is a TestCase that provides faked utility functions.
HostTestCase defines a set of tests without a TestCase.
HostTest creates tests for Host.
FakeHostTest creates tests for FakeHost.
"""
class NonHermeticTestCase(TestCaseWithIO):
"""TestCase that provides real-system utility functions."""
# Unit test "constructor" and "destructor"
def setUp(self):
super(NonHermeticTestCase, self).setUp()
self._host = Host()
self._host.fd_out = self._stdout
self._host.fd_err = self._stderr
self._temp_dir = tempfile.mkdtemp()
def tearDown(self):
shutil.rmtree(self._temp_dir)
self._temp_dir = None
super(NonHermeticTestCase, self).tearDown()
# Unit test context
@property
def host(self):
return self._host
@property
def temp_dir(self):
return self._temp_dir
# Unit test utilities
def isfile(self, pathname):
return os.path.isfile(pathname)
def isdir(self, pathname):
return os.path.isdir(pathname)
def mkdir(self, pathname):
os.makedirs(pathname)
def readfile(self, pathname):
with open(pathname) as opened:
return opened.read().strip()
def writefile(self, pathname, contents=None):
with open(pathname, 'w') as opened:
if contents:
opened.write(contents)
class HermeticTestCase(TestCaseWithIO):
"""TestCase that provides faked utility functions."""
# Unit test "constructor"
def setUp(self):
super(HermeticTestCase, self).setUp()
self._host = FakeHost()
self._host.fd_out = self._stdout
self._host.fd_err = self._stderr
process = self.host.create_process(['false'])
process.succeeds = False
process = self.host.create_process(['echo foo'])
process.schedule(start=0, output='foo')
# Unit test context
@property
def host(self):
return self._host
@property
def temp_dir(self):
return 'temp_dir'
# Unit test utilities
def isfile(self, pathname):
return self.host.isfile(pathname)
def isdir(self, pathname):
return self.host.isdir(pathname)
def mkdir(self, pathname):
self.host.mkdir(pathname)
def readfile(self, pathname):
return self.host.readfile(pathname)
def writefile(self, pathname, contents=None):
with self.host.open(pathname, 'w') as opened:
if contents:
opened.write(contents)
class HostTestCase(object):
"""Defines a set of tests without a TestCase."""
def test_trace(self):
sys.stdout = self._stdout
original = self.host.tracing
try:
# Tracing can be enabled
self.host.tracing = True
self.host.trace('Check one...')
self.assertOut(['+ Check one...'])
# It can be disabled again
self.host.tracing = False
self.host.trace('Check two...')
self.assertOut([])
finally:
sys.stdout = sys.__stdout__
self.host.tracing = original
def test_echo(self):
self.host.echo('Hello world')
self.assertOut(['Hello world'])
def test_error(self):
with self.assertRaises(SystemExit):
self.host.error('Hello world')
self.assertErr(['ERROR: Hello world'])
def test_choose(self):
prompt = 'Pick your favorite animal'
choices = ['cat', 'dog', 'bear']
self.set_input('3')
choice = self.host.choose(prompt, choices)
self.assertEqual(choice, 'bear')
self.set_input('0')
with self.assertRaises(SystemExit):
self.host.choose(prompt, choices)
def test_isdir(self):
pathname = os.path.join(self.temp_dir, 'test_isdir')
self.assertFalse(self.host.isdir(pathname))
self.mkdir(pathname)
self.assertTrue(self.host.isdir(pathname))
def test_isfile(self):
pathname = os.path.join(self.temp_dir, 'test_isfile')
self.assertFalse(self.host.isfile(pathname))
self.writefile(pathname)
self.assertTrue(self.host.isfile(pathname))
def test_glob(self):
foo = os.path.join(self.temp_dir, 'foo')
bar = os.path.join(self.temp_dir, 'bar')
self.writefile(foo)
self.writefile(bar)
files = self.host.glob(os.path.join(self.temp_dir, '*'))
self.assertIn(foo, files)
self.assertIn(bar, files)
def test_open(self):
pathname = os.path.join(self.temp_dir, 'test_open')
with self.assertRaises(SystemExit):
opened = self.host.open(pathname)
self.assertErr(['ERROR: Failed to open {}.'.format(pathname)])
opened = self.host.open(pathname, missing_ok=True)
self.assertFalse(opened)
with self.host.open(pathname, mode='w') as opened:
pass
with self.host.open(pathname) as opened:
pass
def test_readfile(self):
pathname = os.path.join(self.temp_dir, 'test_readfile')
with self.assertRaises(SystemExit):
self.host.readfile(pathname)
self.assertErr(['ERROR: Failed to open {}.'.format(pathname)])
self.assertFalse(self.host.readfile(pathname, missing_ok=True))
self.writefile(pathname, 'data')
self.assertEqual(self.host.readfile(pathname), 'data')
def test_touch(self):
pathname = os.path.join(self.temp_dir, 'test_touch')
self.assertFalse(self.isfile(pathname))
self.host.touch(pathname)
self.assertTrue(self.isfile(pathname))
def test_mkdir(self):
pathname = os.path.join(self.temp_dir, 'test', 'mkdir')
self.assertFalse(self.isdir(pathname))
self.host.mkdir(pathname)
self.assertTrue(self.isdir(pathname))
def test_link(self):
link = os.path.join(self.temp_dir, 'test_link')
foo = os.path.join(self.temp_dir, 'foo')
self.writefile(foo, 'foo')
bar = os.path.join(self.temp_dir, 'bar')
self.writefile(bar, 'bar')
self.host.link(foo, link)
self.writefile(link, 'baz')
self.assertEqual(self.readfile(foo), 'baz')
self.assertEqual(self.readfile(bar), 'bar')
self.host.link(bar, link)
self.writefile(link, 'qux')
self.assertEqual(self.readfile(foo), 'baz')
self.assertEqual(self.readfile(bar), 'qux')
def test_remove(self):
pathname = os.path.join(self.temp_dir, 'test_remove')
self.mkdir(pathname)
self.assertTrue(self.isdir(pathname))
self.host.remove(pathname)
self.assertFalse(self.isdir(pathname))
self.writefile(pathname)
self.assertTrue(self.isfile(pathname))
self.host.remove(pathname)
self.assertFalse(self.isfile(pathname))
def test_temp_dir(self):
with self.host.temp_dir() as temp_dir:
self.assertTrue(self.isdir(temp_dir.pathname))
def test_create_process(self):
self.host.create_process(['true']).call()
with self.assertRaises(subprocess.CalledProcessError):
self.host.create_process(['false']).check_call()
output = self.host.create_process(['echo', 'foo']).check_output()
self.assertEqual(output, 'foo\n')
class HostTest(NonHermeticTestCase, HostTestCase):
"""Creates tests for Host."""
pass
class FakeHostTest(HermeticTestCase, HostTestCase):
"""Creates tests for FakeHost."""
pass
if __name__ == '__main__':
unittest.main()