Rev 4683: Better redirection handling. in file:///home/vila/src/bzr/experimental/shell-like-tests/

Vincent Ladeuil v.ladeuil+lp at free.fr
Fri Sep 11 13:16:09 BST 2009


At file:///home/vila/src/bzr/experimental/shell-like-tests/

------------------------------------------------------------
revno: 4683
revision-id: v.ladeuil+lp at free.fr-20090911121609-4ag5y8wqmpkrqus1
parent: v.ladeuil+lp at free.fr-20090910101617-o36u03has8sqbnpt
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: shell-like-tests
timestamp: Fri 2009-09-11 14:16:09 +0200
message:
  Better redirection handling.
  
  * bzrlib/tests/test_script.py:
  (TestRedirections): Explicit tests for redirections including the
  cases used by Maritza Mendez in the #425510 and $426410 reports.
  
  * bzrlib/tests/script.py:
  (_scan_redirection_options.redirected_file_name): Factor out
  redirection file name handling.
  (_scan_redirection_options): Handle the case where the redirection
  is specified with 2 arguments instead of one.
  (ScriptRunner.run_command): Tweak error message.
  (ScriptRunner.do_cat, ScriptRunner.do_echo): Catch redirection
  errors.
-------------- next part --------------
=== modified file 'bzrlib/tests/script.py'
--- a/bzrlib/tests/script.py	2009-09-10 10:16:17 +0000
+++ b/bzrlib/tests/script.py	2009-09-11 12:16:09 +0000
@@ -210,17 +210,28 @@
         - The mode to open the output file or None
         - The reamining arguments
     """
+    def redirected_file_name(direction, name, args):
+        if name == '':
+            try:
+                name = args.pop(0)
+            except IndexError:
+                # We leave the error handling to higher levels, an empty name
+                # can't be legal.
+                name = ''
+        return name
+
     remaining = []
     in_name = None
     out_name, out_mode = None, None
-    for arg in  args:
+    while args:
+        arg = args.pop(0)
         if arg.startswith('<'):
-            in_name = arg[1:]
+            in_name = redirected_file_name('<', arg[1:], args)
         elif arg.startswith('>>'):
-            out_name = arg[2:]
+            out_name = redirected_file_name('>>', arg[2:], args)
             out_mode = 'ab+'
-        elif arg.startswith('>'):
-            out_name = arg[1:]
+        elif arg.startswith('>',):
+            out_name = redirected_file_name('>', arg[1:], args)
             out_mode = 'wb+'
         else:
             remaining.append(arg)
@@ -270,7 +281,8 @@
         self._check_output(output, actual_output)
         self._check_output(error, actual_error)
         if retcode and not error and actual_error:
-            self.test_case.fail('Unexpected error: %s' % actual_error)
+            self.test_case.fail('In \n\t%s\nUnexpected error: %s'
+                                % (' '.join(cmd), actual_error))
         return retcode, actual_output, actual_error
 
     def _read_input(self, input, in_name):
@@ -306,11 +318,19 @@
             if in_name is not None:
                 raise SyntaxError('Specify a file OR use redirection')
             in_name = args[0]
-        input = self._read_input(input, in_name)
+        try:
+            input = self._read_input(input, in_name)
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                return 1, None, '%s: No such file or directory\n' % (in_name,)
         # Basically cat copy input to output
         output = input
         # Handle output redirections
-        output = self._write_output(output, out_name, out_mode)
+        try:
+            output = self._write_output(output, out_name, out_mode)
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                return 1, None, '%s: No such file or directory\n' % (out_name,)
         return 0, output, None
 
     def do_echo(self, input, args):
@@ -319,13 +339,21 @@
                 raise SyntaxError('Specify parameters OR use redirection')
         if args:
             input = ''.join(args)
-        input = self._read_input(input, in_name)
+        try:
+            input = self._read_input(input, in_name)
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                return 1, None, '%s: No such file or directory\n' % (in_name,)
         # Always append a \n'
         input += '\n'
         # Process output
         output = input
         # Handle output redirections
-        output = self._write_output(output, out_name, out_mode)
+        try:
+            output = self._write_output(output, out_name, out_mode)
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                return 1, None, '%s: No such file or directory\n' % (out_name,)
         return 0, output, None
 
     def _ensure_in_jail(self, path):

=== modified file 'bzrlib/tests/test_script.py'
--- a/bzrlib/tests/test_script.py	2009-09-10 10:16:17 +0000
+++ b/bzrlib/tests/test_script.py	2009-09-11 12:16:09 +0000
@@ -84,6 +84,39 @@
                           script._script_to_commands(story))
 
 
+class TestRedirections(tests.TestCase):
+
+    def _check(self, in_name, out_name, out_mode, remaining, args):
+        self.assertEqual(script._scan_redirection_options(args),
+                         (in_name, out_name, out_mode, remaining))
+
+    def test_no_redirection(self):
+        self._check(None, None, None, [], [])
+        self._check(None, None, None, ['foo', 'bar'], ['foo', 'bar'])
+
+    def test_input_redirection(self):
+        self._check('foo', None, None, [], ['<foo'])
+        self._check('foo', None, None, ['bar'], ['bar', '<foo'])
+        self._check('foo', None, None, ['bar'], ['bar', '<', 'foo'])
+        self._check('foo', None, None, ['bar'], ['<foo', 'bar'])
+        self._check('foo', None, None, ['bar', 'baz'], ['bar', '<foo', 'baz'])
+
+    def test_output_redirection(self):
+        self._check(None, 'foo', 'wb+', [], ['>foo'])
+        self._check(None, 'foo', 'wb+', ['bar'], ['bar', '>foo'])
+        self._check(None, 'foo', 'wb+', ['bar'], ['bar', '>', 'foo'])
+        self._check(None, 'foo', 'ab+', [], ['>>foo'])
+        self._check(None, 'foo', 'ab+', ['bar'], ['bar', '>>foo'])
+        self._check(None, 'foo', 'ab+', ['bar'], ['bar', '>>', 'foo'])
+
+    def test_redirection_syntax_errors(self):
+        self._check('', None, None, [], ['<'])
+        self._check(None, '', 'wb+', [], ['>'])
+        self._check(None, '', 'ab+', [], ['>>'])
+        self._check('>', '', 'ab+', [], ['<', '>', '>>'])
+
+
+
 class TestScriptExecution(script.TestCaseWithTransportAndScript):
 
     def test_unknown_command(self):
@@ -185,6 +218,34 @@
                                              None, None, None)
         self.assertFileEqual('content\n', 'file2')
 
+    def test_cat_bogus_input_file(self):
+        self.run_script("""
+cat <file
+2>file: No such file or directory
+""")
+
+    def test_cat_bogus_output_file(self):
+        self.run_script("""
+cat >
+2>: No such file or directory
+""")
+
+    def test_echo_bogus_input_file(self):
+        # We need a backing file sysytem for that test so it can't be in
+        # TestEcho
+        self.run_script("""
+echo <file
+2>file: No such file or directory
+""")
+
+    def test_echo_bogus_output_file(self):
+        # We need a backing file sysytem for that test so it can't be in
+        # TestEcho
+        self.run_script("""
+echo >
+2>: No such file or directory
+""")
+
 
 class TestMkdir(script.TestCaseWithTransportAndScript):
 



More information about the bazaar-commits mailing list