From 712485a2fef16ee9b1850c7ed634e3d402706286 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Tue, 12 Jan 2010 07:14:49 +0000 Subject: Update Test{Cmd,Common}.py from upstream, with a new TestCommon.must_not_contain() method, new-style classes (inherit from object), and a fix for a Windows race by only opening up a pipe to stdin if we have something to write to it. --- QMTest/TestCmd.py | 40 ++++++++++++++++++++++++++++++---------- QMTest/TestCommon.py | 21 ++++++++++++++++++--- QMTest/TestSCons.py | 12 ++++++++++++ 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index bce7ebb..029c1d0 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -198,7 +198,7 @@ version. TestCmd.where_is('foo', 'PATH1;PATH2', '.suffix3;.suffix4') """ -# Copyright 2000, 2001, 2002, 2003, 2004 Steven Knight +# Copyright 2000-2010 Steven Knight # This module is free software, and you may redistribute it and/or modify # it under the same terms as Python itself, so long as this copyright message # and disclaimer are retained in their original form. @@ -215,8 +215,8 @@ version. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. __author__ = "Steven Knight " -__revision__ = "TestCmd.py 0.36.D001 2009/07/24 08:45:26 knight" -__version__ = "0.36" +__revision__ = "TestCmd.py 0.37.D001 2010/01/11 16:55:50 knight" +__version__ = "0.37" import errno import os @@ -828,7 +828,15 @@ def send_all(p, data): -class TestCmd: +try: + object +except NameError: + class object: + pass + + + +class TestCmd(object): """Class TestCmd """ @@ -989,13 +997,13 @@ class TestCmd: interpreter = None, arguments = None): if program: - if type(program) is type('') and not os.path.isabs(program): + if type(program) == type('') and not os.path.isabs(program): program = os.path.join(self._cwd, program) else: program = self.program if not interpreter: interpreter = self.interpreter - if type(program) not in [type([]), type(())]: + if not type(program) in [type([]), type(())]: program = [program] cmd = list(program) if interpreter: @@ -1003,7 +1011,7 @@ class TestCmd: interpreter = [interpreter] cmd = list(interpreter) + cmd if arguments: - if type(arguments) is type(''): + if type(arguments) == type(''): arguments = string.split(arguments) cmd.extend(arguments) return cmd @@ -1147,6 +1155,14 @@ class TestCmd: if universal_newlines is None: universal_newlines = self.universal_newlines + # On Windows, if we make stdin a pipe when we plan to send + # no input, and the test program exits before + # Popen calls msvcrt.open_osfhandle, that call will fail. + # So don't use a pipe for stdin if we don't need one. + stdin = kw.get('stdin', None) + if stdin is not None: + stdin = subprocess.PIPE + combine = kw.get('combine', self.combine) if combine: stderr_value = subprocess.STDOUT @@ -1154,7 +1170,7 @@ class TestCmd: stderr_value = subprocess.PIPE return Popen(cmd, - stdin=subprocess.PIPE, + stdin=stdin, stdout=subprocess.PIPE, stderr=stderr_value, universal_newlines=universal_newlines) @@ -1196,14 +1212,18 @@ class TestCmd: if self.verbose: sys.stderr.write("chdir(" + chdir + ")\n") os.chdir(chdir) - p = self.start(program, interpreter, arguments, universal_newlines) + p = self.start(program, + interpreter, + arguments, + universal_newlines, + stdin=stdin) if stdin: if is_List(stdin): for line in stdin: p.stdin.write(line) else: p.stdin.write(stdin) - p.stdin.close() + p.stdin.close() out = p.stdout.read() if p.stderr is None: diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 5356fac..4aa7185 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -46,6 +46,8 @@ provided by the TestCommon class: test.must_not_be_writable('file1', ['file2', ...]) + test.must_not_contain('file', 'banned text\n') + test.must_not_contain_any_line(output, lines, ['title', find]) test.must_not_exist('file1', ['file2', ...]) @@ -70,7 +72,7 @@ The TestCommon module also provides the following variables """ -# Copyright 2000, 2001, 2002, 2003, 2004 Steven Knight +# Copyright 2000-2010 Steven Knight # This module is free software, and you may redistribute it and/or modify # it under the same terms as Python itself, so long as this copyright message # and disclaimer are retained in their original form. @@ -87,8 +89,8 @@ The TestCommon module also provides the following variables # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. __author__ = "Steven Knight " -__revision__ = "TestCommon.py 0.36.D001 2009/07/24 08:45:26 knight" -__version__ = "0.36" +__revision__ = "TestCommon.py 0.37.D001 2010/01/11 16:55:50 knight" +__version__ = "0.37" import copy import os @@ -333,6 +335,19 @@ class TestCommon(TestCmd): self.diff(expect, file_contents, 'contents ') raise + def must_not_contain(self, file, banned, mode = 'rb'): + """Ensures that the specified file doesn't contain the banned text. + """ + file_contents = self.read(file, mode) + contains = (string.find(file_contents, banned) != -1) + if contains: + print "File `%s' contains banned string." % file + print self.banner('Banned string ') + print banned + print self.banner('%s contents ' % file) + print file_contents + self.fail_test(contains) + def must_not_contain_any_line(self, output, lines, title=None, find=None): """Ensures that the specified output string (first argument) does not contain any of the specified lines (second argument). diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index bc1ba03..ce01174 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -959,6 +959,18 @@ print py_ver return [python] + string.split(string.strip(self.stdout()), '\n') + def start(self, *args, **kw): + """ + Starts SCons in the test environment. + + This method exists to tell Test{Cmd,Common} that we're going to + use standard input without forcing every .start() call in the + individual tests to do so explicitly. + """ + if not kw.has_key('stdin'): + kw['stdin'] = True + return apply(TestCommon.start, (self,) + args, kw) + def wait_for(self, fname, timeout=10.0, popen=None): """ Waits for the specified file name to exist. -- cgit v0.12