mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 776035 part 2 - Add an enhanced MockedOpen facility to mozunit.py. r=ted
This commit is contained in:
parent
985de147d7
commit
4c48c001f8
@ -161,6 +161,7 @@ PYUNITS := \
|
||||
unit-buildlist.py \
|
||||
unit-expandlibs.py \
|
||||
unit-writemozinfo.py \
|
||||
unit-mozunit.py \
|
||||
$(NULL)
|
||||
|
||||
check-preqs = \
|
||||
|
@ -5,6 +5,8 @@
|
||||
from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
|
||||
import unittest
|
||||
import inspect
|
||||
from StringIO import StringIO
|
||||
import os
|
||||
|
||||
'''Helper to make python unit tests report the way that the Mozilla
|
||||
unit test infrastructure expects tests to report.
|
||||
@ -70,5 +72,68 @@ class MozTestRunner(_TestRunner):
|
||||
result.printErrorList()
|
||||
return result
|
||||
|
||||
class MockedFile(StringIO):
|
||||
def __init__(self, context, filename, content = ''):
|
||||
self.context = context
|
||||
self.name = filename
|
||||
StringIO.__init__(self, content)
|
||||
|
||||
def close(self):
|
||||
self.context.files[self.name] = self.getvalue()
|
||||
StringIO.close(self)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
class MockedOpen(object):
|
||||
'''
|
||||
Context manager diverting the open builtin such that opening files
|
||||
can open "virtual" file instances given when creating a MockedOpen.
|
||||
|
||||
with MockedOpen({'foo': 'foo', 'bar': 'bar'}):
|
||||
f = open('foo', 'r')
|
||||
|
||||
will thus open the virtual file instance for the file 'foo' to f.
|
||||
|
||||
MockedOpen also masks writes, so that creating or replacing files
|
||||
doesn't touch the file system, while subsequently opening the file
|
||||
will return the recorded content.
|
||||
|
||||
with MockedOpen():
|
||||
f = open('foo', 'w')
|
||||
f.write('foo')
|
||||
self.assertRaises(Exception,f.open('foo', 'r'))
|
||||
'''
|
||||
def __init__(self, files = {}):
|
||||
self.files = {}
|
||||
for name, content in files.iteritems():
|
||||
self.files[os.path.abspath(name)] = content
|
||||
|
||||
def __call__(self, name, mode = 'r'):
|
||||
absname = os.path.abspath(name)
|
||||
if 'w' in mode:
|
||||
file = MockedFile(self, absname)
|
||||
elif absname in self.files:
|
||||
file = MockedFile(self, absname, self.files[absname])
|
||||
elif 'a' in mode:
|
||||
file = MockedFile(self, absname, self.open(name, 'r').read())
|
||||
else:
|
||||
file = self.open(name, mode)
|
||||
if 'a' in mode:
|
||||
file.seek(0, os.SEEK_END)
|
||||
return file
|
||||
|
||||
def __enter__(self):
|
||||
import __builtin__
|
||||
self.open = __builtin__.open
|
||||
__builtin__.open = self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
import __builtin__
|
||||
__builtin__.open = self.open
|
||||
|
||||
def main(*args):
|
||||
unittest.main(testRunner=MozTestRunner(),*args)
|
||||
|
75
config/tests/unit-mozunit.py
Normal file
75
config/tests/unit-mozunit.py
Normal file
@ -0,0 +1,75 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import with_statement
|
||||
import sys
|
||||
import os
|
||||
from mozunit import main, MockedOpen
|
||||
import unittest
|
||||
from tempfile import mkstemp
|
||||
|
||||
class TestMozUnit(unittest.TestCase):
|
||||
def test_mocked_open(self):
|
||||
# Create a temporary file on the file system.
|
||||
(fd, path) = mkstemp()
|
||||
with os.fdopen(fd, 'w') as file:
|
||||
file.write('foobar');
|
||||
|
||||
with MockedOpen({'file1': 'content1',
|
||||
'file2': 'content2'}):
|
||||
# Check the contents of the files given at MockedOpen creation.
|
||||
self.assertEqual(open('file1', 'r').read(), 'content1')
|
||||
self.assertEqual(open('file2', 'r').read(), 'content2')
|
||||
|
||||
# Check that overwriting these files alters their content.
|
||||
with open('file1', 'w') as file:
|
||||
file.write('foo')
|
||||
self.assertEqual(open('file1', 'r').read(), 'foo')
|
||||
|
||||
# ... but not until the file is closed.
|
||||
file = open('file2', 'w')
|
||||
file.write('bar')
|
||||
self.assertEqual(open('file2', 'r').read(), 'content2')
|
||||
file.close()
|
||||
self.assertEqual(open('file2', 'r').read(), 'bar')
|
||||
|
||||
# Check that appending to a file does append
|
||||
with open('file1', 'a') as file:
|
||||
file.write('bar')
|
||||
self.assertEqual(open('file1', 'r').read(), 'foobar')
|
||||
|
||||
# Opening a non-existing file ought to fail.
|
||||
self.assertRaises(IOError, open, 'file3', 'r')
|
||||
|
||||
# Check that writing a new file does create the file.
|
||||
with open('file3', 'w') as file:
|
||||
file.write('baz')
|
||||
self.assertEqual(open('file3', 'r').read(), 'baz')
|
||||
|
||||
# Check the content of the file created outside MockedOpen.
|
||||
self.assertEqual(open(path, 'r').read(), 'foobar')
|
||||
|
||||
# Check that overwriting a file existing on the file system
|
||||
# does modify its content.
|
||||
with open(path, 'w') as file:
|
||||
file.write('bazqux')
|
||||
self.assertEqual(open(path, 'r').read(), 'bazqux')
|
||||
|
||||
with MockedOpen():
|
||||
# Check that appending to a file existing on the file system
|
||||
# does modify its content.
|
||||
with open(path, 'a') as file:
|
||||
file.write('bazqux')
|
||||
self.assertEqual(open(path, 'r').read(), 'foobarbazqux')
|
||||
|
||||
# Check that the file was not actually modified on the file system.
|
||||
self.assertEqual(open(path, 'r').read(), 'foobar')
|
||||
os.remove(path)
|
||||
|
||||
# Check that the file created inside MockedOpen wasn't actually
|
||||
# created.
|
||||
self.assertRaises(IOError, open, 'file3', 'r')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user