diff options
author | Steven Knight <knight@baldmt.com> | 2006-12-16 01:43:01 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2006-12-16 01:43:01 (GMT) |
commit | a4fa510f9025ccb4ffeddefe26ce17e01c6a2b8f (patch) | |
tree | 8a0d07c078ac21bf1ab689eacf06577069bb9231 /QMTest | |
parent | cb98bc6c10eb4cc1d29babc180d1dbc74fafe508 (diff) | |
download | SCons-a4fa510f9025ccb4ffeddefe26ce17e01c6a2b8f.zip SCons-a4fa510f9025ccb4ffeddefe26ce17e01c6a2b8f.tar.gz SCons-a4fa510f9025ccb4ffeddefe26ce17e01c6a2b8f.tar.bz2 |
Merged revisions 1675-1736 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core
........
r1689 | stevenknight | 2006-11-06 20:56:29 -0600 (Mon, 06 Nov 2006) | 1 line
0.96.D483 - Merge changes for 0.96.93 packaging from the subsidiary branch.
........
r1690 | stevenknight | 2006-11-06 20:59:30 -0600 (Mon, 06 Nov 2006) | 1 line
0.96.D484 - Update HOWTO for releases. Fix name type in src/CHANGES.txt.
........
r1691 | stevenknight | 2006-11-08 13:55:36 -0600 (Wed, 08 Nov 2006) | 1 line
0.96.D485 - Fix MergeFlags() handling of None values. (John Pye)
........
r1692 | stevenknight | 2006-11-08 17:15:05 -0600 (Wed, 08 Nov 2006) | 1 line
0.96.D486 - Directly execute commands on Windows when possible. (Jay Kint)
........
r1693 | stevenknight | 2006-11-08 18:54:49 -0600 (Wed, 08 Nov 2006) | 1 line
0.96.D487 - Remove the semi-colon from the list of characters that determine when we use cmd
........
r1694 | stevenknight | 2006-11-09 01:34:06 -0600 (Thu, 09 Nov 2006) | 1 line
0.96.D488 - Pick up latex/bibtex 'Rerun to get citations correct' messages. (Dmitry Mikhin)
........
r1695 | stevenknight | 2006-11-11 08:36:33 -0600 (Sat, 11 Nov 2006) | 1 line
0.96.D489 - Back out the direct-execution-on-Windows change until we solve a corner case.
........
r1696 | stevenknight | 2006-11-15 10:33:10 -0600 (Wed, 15 Nov 2006) | 1 line
0.96.D490 - Fix the sconsign script when the .sconsign.dblite file is specified with its suf
........
r1697 | stevenknight | 2006-11-18 10:45:50 -0600 (Sat, 18 Nov 2006) | 4 lines
Complete move of test/sconsign/script.py to underneath test/sconsign/script/.
(This got left out of the previous checkin due to an error in the
script that resubmits Aegis changes to Subversion.)
........
r1698 | stevenknight | 2006-11-18 11:05:26 -0600 (Sat, 18 Nov 2006) | 1 line
0.96.D491 - Allow an Options converter to take the construction environment as a parameter.
........
r1699 | stevenknight | 2006-11-30 15:34:37 -0600 (Thu, 30 Nov 2006) | 1 line
0.96.D492 - Reverse the order in which we try the arguments Options converters, first a sing
........
r1700 | stevenknight | 2006-11-30 16:03:09 -0600 (Thu, 30 Nov 2006) | 1 line
0.96.D493 - Speed up rel_path() by avoiding recomputation of intermediate directory relative
........
r1701 | stevenknight | 2006-11-30 16:14:16 -0600 (Thu, 30 Nov 2006) | 1 line
0.96.D494 - More efficient get_suffix(): compute it once when we set the name.
........
r1702 | stevenknight | 2006-11-30 16:22:55 -0600 (Thu, 30 Nov 2006) | 1 line
0.96.D495 - Fix missing XML end tags.
........
r1703 | stevenknight | 2006-11-30 17:15:25 -0600 (Thu, 30 Nov 2006) | 1 line
0.96.D496 - Turn Memoizer into a simple counter for --debug=memoizer, not something that doe
........
r1704 | stevenknight | 2006-11-30 20:30:50 -0600 (Thu, 30 Nov 2006) | 1 line
0.96.D497 - Add the scons-time script, with doc and tests.
........
r1705 | stevenknight | 2006-11-30 23:28:20 -0600 (Thu, 30 Nov 2006) | 1 line
0.96.D498 - Update the copyright years string.
........
r1706 | stevenknight | 2006-12-01 11:54:22 -0600 (Fri, 01 Dec 2006) | 1 line
0.96.D499 - Fix _do_Lookup => _doLookup value-caching misspellings. (Ben Leslie)
........
r1707 | stevenknight | 2006-12-01 12:03:46 -0600 (Fri, 01 Dec 2006) | 1 line
0.96.D500 - Fix copyright test against debian build. (Walter Franzini)
........
r1708 | stevenknight | 2006-12-01 14:23:29 -0600 (Fri, 01 Dec 2006) | 1 line
0.96.D501 - Add #include lines for test portability. (Gary Oberbrunner)
........
r1709 | stevenknight | 2006-12-01 14:51:12 -0600 (Fri, 01 Dec 2006) | 1 line
0.96.D502 - Fix tests under Python versions with no profiler (pstats module).
........
r1710 | stevenknight | 2006-12-01 20:04:49 -0600 (Fri, 01 Dec 2006) | 1 line
0.96.D503 - Remove unnecessary os.path.normpath() calls. (Gary Oberbrunner)
........
r1711 | stevenknight | 2006-12-01 20:34:31 -0600 (Fri, 01 Dec 2006) | 1 line
0.96.D504 - Accomodate arbitray white space after a SWIG %module keyword. (Anonymous)
........
r1712 | stevenknight | 2006-12-05 14:49:54 -0600 (Tue, 05 Dec 2006) | 1 line
0.96.D506 - Cache substitutions of of Builder source suffixes. Use a new PathList module, and a refactor Node.FS.Rfindalldirs() method, to cache calculations of values like CPPPATH.
........
r1713 | stevenknight | 2006-12-05 18:43:36 -0600 (Tue, 05 Dec 2006) | 1 line
0.96.D507 - Use cached stat() values in diskchecks.
........
r1714 | stevenknight | 2006-12-05 21:11:24 -0600 (Tue, 05 Dec 2006) | 1 line
0.96.D508 - Fix Memoizer hit counts for methods memoizing simple values. Clean up the code for memoizing return values in a dictionary. Fix comments.
........
r1715 | stevenknight | 2006-12-06 07:23:18 -0600 (Wed, 06 Dec 2006) | 1 line
0.96.D369 - More efficient Node.FS.Dir.current() check. Fix some Windows test portability issues.
........
r1716 | stevenknight | 2006-12-06 12:24:32 -0600 (Wed, 06 Dec 2006) | 2 lines
Undo previous checkin (distributed incorrect Aegis change number).
........
r1717 | stevenknight | 2006-12-06 12:34:53 -0600 (Wed, 06 Dec 2006) | 1 line
0.96.D505 - Update ae-{cvs,svn}-ci for newer versions of aetar, and to not truncate descriptions.
........
r1718 | stevenknight | 2006-12-07 23:01:41 -0600 (Thu, 07 Dec 2006) | 1 line
0.96.D509 - Only look for mslink on Windows systems. (Sohail Somani)
........
r1719 | stevenknight | 2006-12-07 23:18:33 -0600 (Thu, 07 Dec 2006) | 1 line
0.96.D510 - Have the D compiler Tool use the same logic for shared libraries, too. (Paolo Invernizzi)
........
r1720 | stevenknight | 2006-12-07 23:29:47 -0600 (Thu, 07 Dec 2006) | 1 line
0.96.D511 - Generalize a JobTests.py test so it doesn't assume a specific order in which the operating system executes the threads.
........
r1721 | stevenknight | 2006-12-07 23:39:37 -0600 (Thu, 07 Dec 2006) | 1 line
0.96.D512 - Back out the Tool/dmd.py change; it breaks shared library linking for other lanuages beside D in the construction environment.
........
r1722 | stevenknight | 2006-12-07 23:47:11 -0600 (Thu, 07 Dec 2006) | 1 line
0.96.D513 - Test fixes: Windows portability, handle changes to Python 2.5 messages.
........
r1723 | stevenknight | 2006-12-08 00:00:13 -0600 (Fri, 08 Dec 2006) | 1 line
0.96.D514 - Change how the 'as' Tool is imported to accomodate the Python 2.6 'as' keyword.
........
r1724 | stevenknight | 2006-12-08 11:19:27 -0600 (Fri, 08 Dec 2006) | 1 line
0.96.D515 - Cache both Node.FS.find_file() and Node.FS.Dri.srcdir_find_file().
........
r1725 | stevenknight | 2006-12-08 17:27:35 -0600 (Fri, 08 Dec 2006) | 1 line
0.96.D516 - Better error when we try to fetch contents from an Entry that doesn't exist. (Tom Parker)
........
r1726 | stevenknight | 2006-12-08 23:28:55 -0600 (Fri, 08 Dec 2006) | 1 line
0.96.D517 - Make sure we pick up the scons-local directory regardless of where we chdir internally.
........
r1727 | stevenknight | 2006-12-11 16:25:53 -0600 (Mon, 11 Dec 2006) | 1 line
0.96.D518 - Cache results of Executor.get_unignored_sources() and Executor.process_sources(). Eliminate some map() and disambiguate() calls when scanning for implicit dependencies.
........
r1728 | stevenknight | 2006-12-12 14:32:22 -0600 (Tue, 12 Dec 2006) | 1 line
0.96.D519 - Fix SideEffect() when -j is used.
........
r1729 | stevenknight | 2006-12-12 16:58:15 -0600 (Tue, 12 Dec 2006) | 1 line
0.96.D520 - Add a srcdir keyword to Builder calls.
........
r1730 | stevenknight | 2006-12-12 21:40:59 -0600 (Tue, 12 Dec 2006) | 1 line
0.96.D521 - TeX/LaTeX updates, including handling files in subdirectories. (Joel B. Mohler, Rob Managan, Dmitry Mikhin)
........
r1731 | stevenknight | 2006-12-14 15:01:02 -0600 (Thu, 14 Dec 2006) | 1 line
0.96.D522 - Propogate TypeErrors during variable substitution for display to the user.
........
r1732 | stevenknight | 2006-12-14 20:01:49 -0600 (Thu, 14 Dec 2006) | 1 line
0.96.D523 - Fix the os.path.join() calls in EnvironmentTests.py.
........
r1733 | stevenknight | 2006-12-15 07:48:22 -0600 (Fri, 15 Dec 2006) | 1 line
0.96.D524 - Fix source directories as dependencies of an Alias (0.96.93 problem found by LilyPond).
........
r1735 | stevenknight | 2006-12-15 12:43:45 -0600 (Fri, 15 Dec 2006) | 1 line
0.96.D525 - Allow printing Debug.caller() output (or other end-of-run debugging info) when using -h.
........
r1736 | stevenknight | 2006-12-15 16:30:08 -0600 (Fri, 15 Dec 2006) | 1 line
0.96.D526 - Add an option to debug IndexError and NameError exceptions during variable substitution.
........
Diffstat (limited to 'QMTest')
-rw-r--r-- | QMTest/SConscript | 2 | ||||
-rw-r--r-- | QMTest/TestCmd.py | 43 | ||||
-rw-r--r-- | QMTest/TestCommon.py | 4 | ||||
-rw-r--r-- | QMTest/TestSCons.py | 24 | ||||
-rw-r--r-- | QMTest/TestSCons_time.py | 365 | ||||
-rw-r--r-- | QMTest/TestSConsign.py | 74 |
6 files changed, 504 insertions, 8 deletions
diff --git a/QMTest/SConscript b/QMTest/SConscript index e016dc4..309f0dc 100644 --- a/QMTest/SConscript +++ b/QMTest/SConscript @@ -37,6 +37,8 @@ files = [ 'TestCommon.py', 'TestRuntest.py', 'TestSCons.py', + 'TestSConsign.py', + 'TestSCons_time.py', 'unittest.py', ] diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 9b3e7a2..7a668e8 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -176,8 +176,8 @@ version. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. __author__ = "Steven Knight <knight at baldmt dot com>" -__revision__ = "TestCmd.py 0.22.D001 2006/02/26 15:45:18 knight" -__version__ = "0.22" +__revision__ = "TestCmd.py 0.23.D001 2006/11/30 13:57:29 knight" +__version__ = "0.23" import os import os.path @@ -193,9 +193,17 @@ import traceback import types import UserList -__all__ = [ 'fail_test', 'no_result', 'pass_test', - 'match_exact', 'match_re', 'match_re_dotall', - 'python_executable', 'TestCmd' ] +__all__ = [ + 'diff_re', + 'fail_test', + 'no_result', + 'pass_test', + 'match_exact', + 'match_re', + 'match_re_dotall', + 'python_executable', + 'TestCmd' +] def is_List(e): return type(e) is types.ListType \ @@ -362,6 +370,31 @@ def match_re_dotall(lines = None, res = None): if re.compile("^" + res + "$", re.DOTALL).match(lines): return 1 +def diff_re(a, b, fromfile='', tofile='', + fromfiledate='', tofiledate='', n=3, lineterm='\n'): + """ + A simple "diff" of two sets of lines when the expected lines + are regular expressions. This is a really dumb thing that + just compares each line in turn, so it doesn't look for + chunks of matching lines and the like--but at least it lets + you know exactly which line first didn't compare correctl... + """ + result = [] + diff = len(a) - len(b) + if diff < 0: + a = a + ['']*(-diff) + elif diff > 0: + b = b + ['']*diff + i = 0 + for aline, bline in zip(a, b): + if not re.compile("^" + aline + "$").search(bline): + result.append("%sc%s" % (i+1, i+1)) + result.append('< ' + repr(a[i])) + result.append('---') + result.append('> ' + repr(b[i])) + i = i+1 + return result + if os.name == 'java': python_executable = os.path.join(sys.prefix, 'jython') diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index b30b75c..b215a26 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -80,8 +80,8 @@ The TestCommon module also provides the following variables # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. __author__ = "Steven Knight <knight at baldmt dot com>" -__revision__ = "TestCommon.py 0.22.D001 2006/02/26 15:45:18 knight" -__version__ = "0.22" +__revision__ = "TestCommon.py 0.23.D001 2006/11/30 13:57:29 knight" +__version__ = "0.23" import os import os.path diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index de15526..091c29f 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -30,7 +30,7 @@ from TestCommon import __all__ # to what we expect. (If we derived the version number from the same # data driving the build we might miss errors if the logic breaks.) -SConsVersion = '0.96.92' +SConsVersion = '0.96.93' __all__.extend([ 'TestSCons', 'python', @@ -303,6 +303,28 @@ class TestSCons(TestCommon): i = i + 1 return "Actual matched the expected output???" + def python_file_line(self, file, line): + """ + Returns a Python error line for output comparisons. + + The exec of the traceback line gives us the correct format for + this version of Python. Before 2.5, this yielded: + + File "<string>", line 1, ? + + Python 2.5 changed this to: + + File "<string>", line 1, <module> + + We stick the requested file name and line number in the right + places, abstracting out the version difference. + """ + exec 'import traceback; x = traceback.format_stack()[-1]' + x = string.lstrip(x) + x = string.replace(x, '<string>', file) + x = string.replace(x, 'line 1,', 'line %s,' % line) + return x + def java_ENV(self): """ Return a default external environment that uses a local Java SDK diff --git a/QMTest/TestSCons_time.py b/QMTest/TestSCons_time.py new file mode 100644 index 0000000..90eb5a8 --- /dev/null +++ b/QMTest/TestSCons_time.py @@ -0,0 +1,365 @@ +""" +TestSCons_time.py: a testing framework for the scons-test.py script + +A TestSCons_time environment object is created via the usual invocation: + + test = TestSCons_time() + +TestSCons_time is a subclass of TestCommon, which is in turn is a subclass +of TestCmd), and hence has available all of the methods and attributes +from those classes, as well as any overridden or additional methods or +attributes defined in this subclass. +""" + +# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation + +__revision__ = "QMTest/TestSCons_time.py 0.96.C629 2006/11/19 06:39:17 knight" + +import os +import os.path +import string +import sys + +from TestCommon import * +from TestCommon import __all__ + +__all__.extend([ 'TestSCons', + 'python', + '_exe', + '_obj', + '_shobj', + 'lib_', + '_lib', + 'dll_', + '_dll' + ]) + +python = python_executable +_python_ = '"' + python_executable + '"' + +SConstruct = """\ +import os +print "SConstruct file directory:", os.getcwd() +""" + +scons_py = """\ +#!/usr/bin/env python +import os +import sys +def write_args(fp, args): + fp.write(args[0] + '\\n') + for arg in args[1:]: + fp.write(' ' + arg + '\\n') +write_args(sys.stdout, sys.argv) +for arg in sys.argv[1:]: + if arg[:10] == '--profile=': + profile = open(arg[10:], 'wb') + profile.write('--profile\\n') + write_args(profile, sys.argv) + break +sys.stdout.write('SCONS_LIB_DIR = ' + os.environ['SCONS_LIB_DIR'] + '\\n') +execfile('SConstruct') +""" + +aegis_py = """\ +#!/usr/bin/env python +import os +import sys +script_dir = 'src/script' +if not os.path.exists(script_dir): + os.makedirs(script_dir) +open(script_dir + '/scons.py', 'w').write( +r'''%s''') +""" % scons_py + + +svn_py = """\ +#!/usr/bin/env python +import os +import sys +dir = sys.argv[-1] +script_dir = dir + '/src/script' +os.makedirs(script_dir) +open(script_dir + '/scons.py', 'w').write( +r'''%s''') +""" % scons_py + + +logfile_contents = """\ +Memory before reading SConscript files: 100%(index)s +Memory after reading SConscript files: 200%(index)s +Memory before building targets: 300%(index)s +Memory after building targets: 400%(index)s +Object counts: + pre- post- pre- post- + read read build build Class + 101%(index)s 102%(index)s 103%(index)s 104%(index)s Action.CommandAction + 201%(index)s 202%(index)s 203%(index)s 204%(index)s Action.CommandGeneratorAction + 301%(index)s 302%(index)s 303%(index)s 304%(index)s Action.FunctionAction + 401%(index)s 402%(index)s 403%(index)s 404%(index)s Action.LazyAction + 501%(index)s 502%(index)s 503%(index)s 504%(index)s Action.ListAction + 601%(index)s 602%(index)s 603%(index)s 604%(index)s Builder.BuilderBase + 701%(index)s 702%(index)s 703%(index)s 704%(index)s Builder.CompositeBuilder + 801%(index)s 802%(index)s 803%(index)s 804%(index)s Builder.ListBuilder + 901%(index)s 902%(index)s 903%(index)s 904%(index)s Builder.MultiStepBuilder + 1001%(index)s 1002%(index)s 1003%(index)s 1004%(index)s Builder.OverrideWarner + 1101%(index)s 1102%(index)s 1103%(index)s 1104%(index)s Environment.Base + 1201%(index)s 1202%(index)s 1203%(index)s 1204%(index)s Environment.EnvironmentClone + 1301%(index)s 1302%(index)s 1303%(index)s 1304%(index)s Environment.OverrideEnvironment + 1401%(index)s 1402%(index)s 1403%(index)s 1404%(index)s Executor.Executor + 1501%(index)s 1502%(index)s 1503%(index)s 1504%(index)s Node.FS + 1601%(index)s 1602%(index)s 1603%(index)s 1604%(index)s Node.FS.Base + 1701%(index)s 1702%(index)s 1703%(index)s 1704%(index)s Node.FS.Dir + 1801%(index)s 1802%(index)s 1803%(index)s 1804%(index)s Node.FS.File + 1901%(index)s 1902%(index)s 1904%(index)s 1904%(index)s Node.FS.RootDir + 2001%(index)s 2002%(index)s 2003%(index)s 2004%(index)s Node.Node +Total build time: 11.123456 seconds +Total SConscript file execution time: 22.234567 seconds +Total SCons execution time: 33.345678 seconds +Total command execution time: 44.456789 seconds +""" + + +profile_py = """\ +%(body)s + +import profile + +try: dispatch = profile.Profile.dispatch +except AttributeError: pass +else: dispatch['c_exception'] = profile.Profile.trace_dispatch_return + +prof = profile.Profile() +prof.runcall(%(call)s) +prof.dump_stats(r'%(profile_name)s') +""" + + +class TestSCons_time(TestCommon): + """Class for testing the scons-time script. + + This provides a common place for initializing scons-time tests, + eliminating the need to begin every test with the same repeated + initializations. + """ + + def __init__(self, **kw): + """Initialize an SCons_time testing object. + + If they're not overridden by keyword arguments, this + initializes the object with the following default values: + + program = 'scons-time' + interpreter = ['python', '-tt'] + match = match_exact + workdir = '' + + The workdir value means that, by default, a temporary workspace + directory is created for a TestSCons_time environment. + In addition, this method changes directory (chdir) to the + workspace directory, so an explicit "chdir = '.'" on all of the + run() method calls is not necessary. + """ + + self.orig_cwd = os.getcwd() + try: + script_dir = os.environ['SCONS_SCRIPT_DIR'] + except KeyError: + pass + else: + os.chdir(script_dir) + if not kw.has_key('program'): + p = os.environ.get('SCONS_TIME') + if not p: + p = 'scons-time' + if not os.path.exists(p): + p = 'scons-time.py' + kw['program'] = p + + if not kw.has_key('interpreter'): + kw['interpreter'] = [python, '-tt'] + + if not kw.has_key('match'): + kw['match'] = match_exact + + if not kw.has_key('workdir'): + kw['workdir'] = '' + + apply(TestCommon.__init__, [self], kw) + + try: + eval('[x for x in [1, 2]]') + except SyntaxError: + version = string.split(sys.version)[0] + msg = 'scons-time does not work on Python version %s\n' % version + self.skip_test(msg) + + def archive_split(self, path): + if path[-7:] == '.tar.gz': + return path[:-7], path[-7:] + else: + return os.path.splitext(path) + + def must_contain_all_lines(self, name, content, expected, exists=None): + missing_lines = [] + + if exists is None: + exists = lambda e, c: string.find(c, e) != -1 + + for e in expected: + if not exists(e, content): + missing_lines.append(e) + + if missing_lines: + sys.stdout.write('%s is missing expected string(s):\n' % name) + for m in missing_lines: + sys.stdout.write(' ' + repr(m) + '\n') + sys.stdout.write('%s content:\n' % name) + sys.stdout.write(content) + self.fail_test() + + def fake_logfile(self, logfile_name, index=0): + self.write(self.workpath(logfile_name), logfile_contents % locals()) + + def profile_data(self, profile_name, python_name, call, body): + profile_name = self.workpath(profile_name) + python_name = self.workpath(python_name) + d = { + 'profile_name' : profile_name, + 'python_name' : python_name, + 'call' : call, + 'body' : body, + } + self.write(python_name, profile_py % d) + self.run(program = python_name, interpreter = sys.executable) + + def skip_test(self, message="Skipping test.\n"): + """Skips a test. + + Proper test-skipping behavior is dependent on whether we're being + executed as part of development of a change under Aegis. + + Technically, skipping a test is a NO RESULT, but Aegis will + treat that as a test failure and prevent the change from going + to the next step. We don't want to force anyone using Aegis + to have to install absolutely every tool used by the tests, + so we actually report to Aegis that a skipped test has PASSED + so that the workflow isn't held up. + """ + if message: + sys.stdout.write(message) + sys.stdout.flush() + devdir = os.popen("aesub '$dd' 2>/dev/null", "r").read()[:-1] + intdir = os.popen("aesub '$intd' 2>/dev/null", "r").read()[:-1] + if devdir and self._cwd[:len(devdir)] == devdir or \ + intdir and self._cwd[:len(intdir)] == intdir: + # We're under the development directory for this change, + # so this is an Aegis invocation; pass the test (exit 0). + self.pass_test() + else: + # skip=1 means skip this function when showing where this + # result came from. They only care about the line where the + # script called test.skip_test(), not the line number where + # we call test.no_result(). + self.no_result(skip=1) + + def write_fake_aegis_py(self, name): + name = self.workpath(name) + self.write(name, aegis_py) + os.chmod(name, 0755) + return name + + def write_fake_scons_py(self): + self.subdir('src', ['src', 'script']) + self.write('src/script/scons.py', scons_py) + + def write_fake_svn_py(self, name): + name = self.workpath(name) + self.write(name, svn_py) + os.chmod(name, 0755) + return name + + def write_sample_directory(self, archive, dir, files): + dir = self.workpath(dir) + for name, content in files: + path = os.path.join(dir, name) + d, f = os.path.split(path) + if not os.path.isdir(d): + os.makedirs(d) + open(path, 'wb').write(content) + return dir + + def write_sample_tarfile(self, archive, dir, files): + import shutil + try: + import tarfile + + except ImportError: + + self.skip_test('no tarfile module\n') + + else: + + base, suffix = self.archive_split(archive) + + mode = { + '.tar' : 'w', + '.tar.gz' : 'w:gz', + '.tgz' : 'w:gz', + } + + tar = tarfile.open(archive, mode[suffix]) + for name, content in files: + path = os.path.join(dir, name) + open(path, 'wb').write(content) + tarinfo = tar.gettarinfo(path, path) + tarinfo.uid = 111 + tarinfo.gid = 111 + tarinfo.uname = 'fake_user' + tarinfo.gname = 'fake_group' + tar.addfile(tarinfo, open(path, 'rb')) + tar.close() + shutil.rmtree(dir) + return self.workpath(archive) + + def write_sample_zipfile(self, archive, dir, files): + import shutil + try: + import zipfile + except ImportError: + + sys.stderr.write('no zipfile module\n') + self.no_result() + + else: + + zip = zipfile.ZipFile(archive, 'w') + for name, content in files: + path = os.path.join(dir, name) + open(path, 'wb').write(content) + zip.write(path) + zip.close() + shutil.rmtree(dir) + return self.workpath(archive) + + sample_project_files = [ + ('SConstruct', SConstruct), + ] + + def write_sample_project(self, archive, dir=None): + base, suffix = self.archive_split(archive) + + write_sample = { + '.tar' : self.write_sample_tarfile, + '.tar.gz' : self.write_sample_tarfile, + '.tgz' : self.write_sample_tarfile, + '.zip' : self.write_sample_zipfile, + }.get(suffix, self.write_sample_directory) + + if not dir: + dir = base + + os.mkdir(dir) + path = write_sample(archive, dir, self.sample_project_files) + + return path diff --git a/QMTest/TestSConsign.py b/QMTest/TestSConsign.py new file mode 100644 index 0000000..d144040 --- /dev/null +++ b/QMTest/TestSConsign.py @@ -0,0 +1,74 @@ +# __COPYRIGHT__ + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """ +TestSConsign.py: a testing framework for the "sconsign" script +tool. + +A TestSConsign environment object is created via the usual invocation: + + test = TestSConsign() + +TestSconsign is a subclass of TestSCons, which is a subclass of +TestCommon, which is in turn is a subclass of TestCmd), and hence +has available all of the methods and attributes from those classes, +as well as any overridden or additional methods or attributes defined +in this subclass. +""" + +import os +import os.path +import string +import sys + +from TestSCons import * +from TestSCons import __all__ + +__all__.extend([ 'TestSConsign', ]) + +class TestSConsign(TestSCons): + """Class for testing the sconsign.py script. + + This provides a common place for initializing sconsign tests, + eliminating the need to begin every test with the same repeated + initializations. + + This adds additional methods for running the sconsign script + without changing the basic ability of the run() method to run + "scons" itself, since we need to run scons to generate the + .sconsign files that we want the sconsign script to read. + """ + def __init__(self, *args, **kw): + try: + script_dir = os.environ['SCONS_SCRIPT_DIR'] + except KeyError: + pass + else: + os.chdir(script_dir) + self.script_dir = os.getcwd() + + apply(TestSCons.__init__, (self,)+args, kw) + + self.my_kw = { + 'interpreter' : python, # imported from TestSCons + } + + if os.path.exists(self.script_path('sconsign.py')): + sconsign = 'sconsign.py' + elif os.path.exists(self.script_path('sconsign')): + sconsign = 'sconsign' + else: + print "Can find neither 'sconsign.py' nor 'sconsign' scripts." + self.no_result() + self.set_sconsign(sconsign) + + def script_path(self, script): + return os.path.join(self.script_dir, script) + + def set_sconsign(self, sconsign): + self.my_kw['program'] = sconsign + + def run_sconsign(self, *args, **kw): + kw.update(self.my_kw) + return apply(self.run, args, kw) |