diff -r 1cd2082ade48 Lib/test/test_fileinput.py --- a/Lib/test/test_fileinput.py Sun Mar 13 22:49:44 2011 -0400 +++ b/Lib/test/test_fileinput.py Mon Mar 14 17:48:07 2011 -0400 @@ -9,11 +9,11 @@ import sys, re from io import StringIO from fileinput import FileInput, hook_encoded +import fileinput # The fileinput module has 2 interfaces: the FileInput class which does # all the work, and a few functions (input, etc.) that use a global _state -# variable. We only test the FileInput class, since the other functions -# only provide a thin facade over FileInput. +# variable. # Write lines (a list of lines) to temp file number i, and return the # temp file's name. @@ -254,9 +254,340 @@ finally: remove_tempfiles(t1) +class MockFileInput: + """A class that mocks out fileinput.FileInput for use during unit tests""" + + def __init__(self, files=None, inplace=False, backup="", bufsize=0, mode="r", openhook=None): + self.files = files + self.inplace = inplace + self.backup = backup + self.bufsize = bufsize + self.mode = mode + self.openhook = openhook + self._file = None + self.num_close_invocations = 0 + self.num_nextfile_invocations = 0 + self.nextfile_retval = None + self.num_filename_invocations = 0 + self.filename_retval = None + self.num_lineno_invocations = 0 + self.lineno_retval = None + self.num_filelineno_invocations = 0 + self.filelineno_retval = None + self.num_fileno_invocations = 0 + self.fileno_retval = None + self.num_isfirstline_invocations = 0 + self.isfirstline_retval = None + self.num_isstdin_invocations = 0 + self.isstdin_retval = None + + def close(self): + self.num_close_invocations += 1 + + def nextfile(self): + self.num_nextfile_invocations += 1 + return self.nextfile_retval + + def filename(self): + self.num_filename_invocations += 1 + return self.filename_retval + + def lineno(self): + self.num_lineno_invocations += 1 + return self.lineno_retval + + def filelineno(self): + self.num_filelineno_invocations += 1 + return self.filelineno_retval + + def fileno(self): + self.num_fileno_invocations += 1 + return self.fileno_retval + + def isfirstline(self): + self.num_isfirstline_invocations += 1 + return self.isfirstline_retval + + def isstdin(self): + self.num_isstdin_invocations += 1 + return self.isstdin_retval + +class BaseFileInputGlobalMethodsTest(unittest.TestCase): + """Base class for unit tests for the global function of the fileinput module.""" + + def setUp(self): + self._orig_state = fileinput._state + self._orig_FileInput = fileinput.FileInput + fileinput.FileInput = MockFileInput + + def tearDown(self): + fileinput.FileInput = self._orig_FileInput + fileinput._state = self._orig_state + +class Test_fileinput_input(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.input()""" + + def test_state_is_not_None_and_state_file_is_not_None(self): + """Tests invoking fileinput.input() when fileinput._state is not None and its _file + attribute is also not None. Expect RuntimeError to be raised with a meaningful error + message and for fileinput._state to *not* be modified.""" + instance = MockFileInput() + instance._file = object() + fileinput._state = instance + with self.assertRaises(RuntimeError) as cm: + fileinput.input() + self.assertEqual(("input() already active",), cm.exception.args) + self.assertIs(instance, fileinput._state, "fileinput._state") + + def test_state_is_not_None_and_state_file_is_None(self): + """Tests invoking fileinput.input() when fileinput._state is not None but its _file + attribute *is* None. Expect it to create and return a new fileinput.FileInput object with + all method parameters passed explicitly to the __init__() method; also ensure that + fileinput._state is set to the returned instance.""" + instance = MockFileInput() + instance._file = None + fileinput._state = instance + self.do_test_call_input() + + def test_state_is_None(self): + """Tests invoking fileinput.input() when fileinput._state is None Expect it to create and + return a new fileinput.FileInput object with all method parameters passed explicitly to the + __init__() method; also ensure that fileinput._state is set to the returned instance.""" + fileinput._state = None + self.do_test_call_input() + + def do_test_call_input(self): + """Tests that fileinput.input() creates a new fileinput.FileInput object, passing the given + parameters unmodified to fileinput.FileInput.__init__(). Note that this test depends on th + monkey patching of fileinput.FileInput done by setUp().""" + files = object() + inplace = object() + backup = object() + bufsize = object() + mode = object() + openhook = object() + + # call fileinput.input() with different values for each keyword argument + result = fileinput.input(files=files, inplace=inplace, backup=backup, bufsize=bufsize, + mode=mode, openhook=openhook) + + # ensure fileinput._state was set to the returned object + self.assertIs(result, fileinput._state, "fileinput._state") + + # ensure the parameters to fileinput.input() were passed directly to FileInput.__init__() + self.assertIs(files, result.files, "files") + self.assertIs(inplace, result.inplace, "inplace") + self.assertIs(backup, result.backup, "backup") + self.assertIs(bufsize, result.bufsize, "bufsize") + self.assertIs(mode, result.mode, "mode") + self.assertIs(openhook, result.openhook, "openhook") + +class Test_fileinput_close(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.close()""" + + def test_state_is_None(self): + """Tests that fileinput.close() does nothing if fileinput._state is None""" + fileinput._state = None + fileinput.close() + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests that fileinput.close() invokes close() on fileinput._state and sets _state=None""" + instance = MockFileInput() + fileinput._state = instance + fileinput.close() + self.assertEqual(instance.num_close_invocations, 1) + self.assertIsNone(fileinput._state) + +class Test_fileinput_nextfile(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.nextfile()""" + + def test_state_is_None(self): + """Tests fileinput.nextfile() when fileinput._state is None. Ensure that it raises + RuntimeError with a meaningful error message and does not modify fileinput._state""" + fileinput._state = None + with self.assertRaises(RuntimeError) as cm: + fileinput.nextfile() + self.assertEqual(("no active input()",), cm.exception.args) + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests fileinput.nextfile() when fileinput._state is not None. Ensure that it invokes + fileinput._state.nextfile() exactly once, returns whatever it returns, and does not modify + fileinput._state to point to a different object.""" + nextfile_retval = object() + instance = MockFileInput() + instance.nextfile_retval = nextfile_retval + fileinput._state = instance + retval = fileinput.nextfile() + self.assertEqual(instance.num_nextfile_invocations, 1) + self.assertIs(retval, nextfile_retval) + self.assertIs(fileinput._state, instance) + +class Test_fileinput_filename(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.filename()""" + + def test_state_is_None(self): + """Tests fileinput.filename() when fileinput._state is None. Ensure that it raises + RuntimeError with a meaningful error message and does not modify fileinput._state""" + fileinput._state = None + with self.assertRaises(RuntimeError) as cm: + fileinput.filename() + self.assertEqual(("no active input()",), cm.exception.args) + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests fileinput.filename() when fileinput._state is not None. Ensure that it invokes + fileinput._state.filename() exactly once, returns whatever it returns, and does not modify + fileinput._state to point to a different object.""" + filename_retval = object() + instance = MockFileInput() + instance.filename_retval = filename_retval + fileinput._state = instance + retval = fileinput.filename() + self.assertEqual(instance.num_filename_invocations, 1) + self.assertIs(retval, filename_retval) + self.assertIs(fileinput._state, instance) + +class Test_fileinput_lineno(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.lineno()""" + + def test_state_is_None(self): + """Tests fileinput.lineno() when fileinput._state is None. Ensure that it raises + RuntimeError with a meaningful error message and does not modify fileinput._state""" + fileinput._state = None + with self.assertRaises(RuntimeError) as cm: + fileinput.lineno() + self.assertEqual(("no active input()",), cm.exception.args) + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests fileinput.lineno() when fileinput._state is not None. Ensure that it invokes + fileinput._state.lineno() exactly once, returns whatever it returns, and does not modify + fileinput._state to point to a different object.""" + lineno_retval = object() + instance = MockFileInput() + instance.lineno_retval = lineno_retval + fileinput._state = instance + retval = fileinput.lineno() + self.assertEqual(instance.num_lineno_invocations, 1) + self.assertIs(retval, lineno_retval) + self.assertIs(fileinput._state, instance) + +class Test_fileinput_filelineno(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.filelineno()""" + + def test_state_is_None(self): + """Tests fileinput.filelineno() when fileinput._state is None. Ensure that it raises + RuntimeError with a meaningful error message and does not modify fileinput._state""" + fileinput._state = None + with self.assertRaises(RuntimeError) as cm: + fileinput.filelineno() + self.assertEqual(("no active input()",), cm.exception.args) + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests fileinput.filelineno() when fileinput._state is not None. Ensure that it invokes + fileinput._state.filelineno() exactly once, returns whatever it returns, and does not modify + fileinput._state to point to a different object.""" + filelineno_retval = object() + instance = MockFileInput() + instance.filelineno_retval = filelineno_retval + fileinput._state = instance + retval = fileinput.filelineno() + self.assertEqual(instance.num_filelineno_invocations, 1) + self.assertIs(retval, filelineno_retval) + self.assertIs(fileinput._state, instance) + +class Test_fileinput_fileno(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.fileno()""" + + def test_state_is_None(self): + """Tests fileinput.fileno() when fileinput._state is None. Ensure that it raises + RuntimeError with a meaningful error message and does not modify fileinput._state""" + fileinput._state = None + with self.assertRaises(RuntimeError) as cm: + fileinput.fileno() + self.assertEqual(("no active input()",), cm.exception.args) + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests fileinput.fileno() when fileinput._state is not None. Ensure that it invokes + fileinput._state.fileno() exactly once, returns whatever it returns, and does not modify + fileinput._state to point to a different object.""" + fileno_retval = object() + instance = MockFileInput() + instance.fileno_retval = fileno_retval + fileinput._state = instance + retval = fileinput.fileno() + self.assertEqual(instance.num_fileno_invocations, 1) + self.assertIs(retval, fileno_retval) + self.assertIs(fileinput._state, instance) + +class Test_fileinput_isfirstline(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.isfirstline()""" + + def test_state_is_None(self): + """Tests fileinput.isfirstline() when fileinput._state is None. Ensure that it raises + RuntimeError with a meaningful error message and does not modify fileinput._state""" + fileinput._state = None + with self.assertRaises(RuntimeError) as cm: + fileinput.isfirstline() + self.assertEqual(("no active input()",), cm.exception.args) + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests fileinput.isfirstline() when fileinput._state is not None. Ensure that it invokes + fileinput._state.isfirstline() exactly once, returns whatever it returns, and does not modify + fileinput._state to point to a different object.""" + isfirstline_retval = object() + instance = MockFileInput() + instance.isfirstline_retval = isfirstline_retval + fileinput._state = instance + retval = fileinput.isfirstline() + self.assertEqual(instance.num_isfirstline_invocations, 1) + self.assertIs(retval, isfirstline_retval) + self.assertIs(fileinput._state, instance) + +class Test_fileinput_isstdin(BaseFileInputGlobalMethodsTest): + """Unit tests for fileinput.isstdin()""" + + def test_state_is_None(self): + """Tests fileinput.isstdin() when fileinput._state is None. Ensure that it raises + RuntimeError with a meaningful error message and does not modify fileinput._state""" + fileinput._state = None + with self.assertRaises(RuntimeError) as cm: + fileinput.isstdin() + self.assertEqual(("no active input()",), cm.exception.args) + self.assertIsNone(fileinput._state) + + def test_state_is_not_None(self): + """Tests fileinput.isstdin() when fileinput._state is not None. Ensure that it invokes + fileinput._state.isstdin() exactly once, returns whatever it returns, and does not modify + fileinput._state to point to a different object.""" + isstdin_retval = object() + instance = MockFileInput() + instance.isstdin_retval = isstdin_retval + fileinput._state = instance + retval = fileinput.isstdin() + self.assertEqual(instance.num_isstdin_invocations, 1) + self.assertIs(retval, isstdin_retval) + self.assertIs(fileinput._state, instance) def test_main(): - run_unittest(BufferSizesTests, FileInputTests) + run_unittest( + BufferSizesTests, + FileInputTests, + Test_fileinput_input, + Test_fileinput_close, + Test_fileinput_nextfile, + Test_fileinput_filename, + Test_fileinput_lineno, + Test_fileinput_filelineno, + Test_fileinput_fileno, + Test_fileinput_isfirstline, + Test_fileinput_isstdin, + ) if __name__ == "__main__": test_main()