diff options
Diffstat (limited to 'src/engine/SCons/cppTests.py')
-rw-r--r-- | src/engine/SCons/cppTests.py | 715 |
1 files changed, 715 insertions, 0 deletions
diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py new file mode 100644 index 0000000..5bd08f8 --- /dev/null +++ b/src/engine/SCons/cppTests.py @@ -0,0 +1,715 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "src/engine/SCons/cppTests.py 4577 2009/12/27 19:44:43 scons" + +import string +import sys +import unittest + +import cpp + + + +basic_input = """ +#include "file1-yes" +#include <file2-yes> +""" + + +substitution_input = """ +#define FILE3 "file3-yes" +#define FILE4 <file4-yes> + +#include FILE3 +#include FILE4 + +#define XXX_FILE5 YYY_FILE5 +#define YYY_FILE5 ZZZ_FILE5 +#define ZZZ_FILE5 FILE5 + +#define FILE5 "file5-yes" +#define FILE6 <file6-yes> + +#define XXX_FILE6 YYY_FILE6 +#define YYY_FILE6 ZZZ_FILE6 +#define ZZZ_FILE6 FILE6 + +#include XXX_FILE5 +#include XXX_FILE6 +""" + + +ifdef_input = """ +#define DEFINED 0 + +#ifdef DEFINED +#include "file7-yes" +#else +#include "file7-no" +#endif + +#ifdef NOT_DEFINED +#include <file8-no> +#else +#include <file8-yes> +#endif +""" + + +if_boolean_input = """ +#define ZERO 0 +#define ONE 1 + +#if ZERO +#include "file9-no" +#else +#include "file9-yes" +#endif + +#if ONE +#include <file10-yes> +#else +#include <file10-no> +#endif + +#if ZERO +#include "file11-no-1" +#elif ZERO +#include "file11-no-2" +#else +#include "file11-yes" +#endif + +#if ZERO +#include <file12-no-1> +#elif ONE +#include <file12-yes> +#else +#include <file12-no-2> +#endif + +#if ONE +#include "file13-yes" +#elif ZERO +#include "file13-no-1" +#else +#include "file13-no-2" +#endif + +#if ONE +#include <file14-yes> +#elif ONE +#include <file14-no-1> +#else +#include <file14-no-2> +#endif +""" + + +if_defined_input = """ +#define DEFINED 0 + +#if defined(DEFINED) +#include "file15-yes" +#endif + +#if ! defined(DEFINED) +#include <file16-no> +#else +#include <file16-yes> +#endif + +#if defined DEFINED +#include "file17-yes" +#endif + +#if ! defined DEFINED +#include <file18-no> +#else +#include <file18-yes> +#endif +""" + + +expression_input = """ +#define ZERO 0 +#define ONE 1 + +#if ZERO && ZERO +#include "file19-no" +#else +#include "file19-yes" +#endif + +#if ZERO && ONE +#include <file20-no> +#else +#include <file20-yes> +#endif + +#if ONE && ZERO +#include "file21-no" +#else +#include "file21-yes" +#endif + +#if ONE && ONE +#include <file22-yes> +#else +#include <file22-no> +#endif + +#if ZERO || ZERO +#include "file23-no" +#else +#include "file23-yes" +#endif + +#if ZERO || ONE +#include <file24-yes> +#else +#include <file24-no> +#endif + +#if ONE || ZERO +#include "file25-yes" +#else +#include "file25-no" +#endif + +#if ONE || ONE +#include <file26-yes> +#else +#include <file26-no> +#endif + +#if ONE == ONE +#include "file27-yes" +#else +#include "file27-no" +#endif + +#if ONE != ONE +#include <file28-no> +#else +#include <file28-yes> +#endif + +#if ! (ONE == ONE) +#include "file29-no" +#else +#include "file29-yes" +#endif + +#if ! (ONE != ONE) +#include <file30-yes> +#else +#include <file30-no> +#endif +""" + + +undef_input = """ +#define UNDEFINE 0 + +#ifdef UNDEFINE +#include "file31-yes" +#else +#include "file31-no" +#endif + +#undef UNDEFINE + +#ifdef UNDEFINE +#include <file32-no> +#else +#include <file32-yes> +#endif +""" + + +macro_function_input = """ +#define ZERO 0 +#define ONE 1 + +#define FUNC33(x) "file33-yes" +#define FUNC34(x) <file34-yes> + +#include FUNC33(ZERO) +#include FUNC34(ZERO) + +#define FILE35 "file35-yes" +#define FILE36 <file36-yes> + +#define FUNC35(x, y) FILE35 +#define FUNC36(x, y) FILE36 + +#include FUNC35(ZERO, ONE) +#include FUNC36(ZERO, ONE) + +#define FILE37 "file37-yes" +#define FILE38 <file38-yes> + +#define FUNC37a(x, y) FILE37 +#define FUNC38a(x, y) FILE38 + +#define FUNC37b(x, y) FUNC37a(x, y) +#define FUNC38b(x, y) FUNC38a(x, y) + +#define FUNC37c(x, y) FUNC37b(x, y) +#define FUNC38c(x, y) FUNC38b(x, y) + +#include FUNC37c(ZERO, ONE) +#include FUNC38c(ZERO, ONE) + +#define FILE39 "file39-yes" +#define FILE40 <file40-yes> + +#define FUNC39a(x0, y0) FILE39 +#define FUNC40a(x0, y0) FILE40 + +#define FUNC39b(x1, y2) FUNC39a(x1, y1) +#define FUNC40b(x1, y2) FUNC40a(x1, y1) + +#define FUNC39c(x2, y2) FUNC39b(x2, y2) +#define FUNC40c(x2, y2) FUNC40b(x2, y2) + +#include FUNC39c(ZERO, ONE) +#include FUNC40c(ZERO, ONE) + +/* Make sure we don't die if the expansion isn't a string. */ +#define FUNC_INTEGER(x) 1 + +/* Make sure one-character names are recognized. */ +#define _(x) translate(x) +#undef _ +""" + + +token_pasting_input = """ +#define PASTE_QUOTE(q, name) q##name##-yes##q +#define PASTE_ANGLE(name) <##name##-yes> + +#define FUNC41 PASTE_QUOTE(", file41) +#define FUNC42 PASTE_ANGLE(file42) + +#include FUNC41 +#include FUNC42 +""" + + +no_space_input = """ +#include<file43-yes> +#include"file44-yes" +""" + + + +# pp_class = PreProcessor +# #pp_class = DumbPreProcessor + +# pp = pp_class(current = ".", +# cpppath = ['/usr/include'], +# print_all = 1) +# #pp(open(sys.argv[1]).read()) +# pp(input) + + +class cppTestCase(unittest.TestCase): + def setUp(self): + self.cpp = self.cpp_class(current = ".", + cpppath = ['/usr/include']) + + def test_basic(self): + """Test basic #include scanning""" + expect = self.basic_expect + result = self.cpp.process_contents(basic_input) + assert expect == result, (expect, result) + + def test_substitution(self): + """Test substitution of #include files using CPP variables""" + expect = self.substitution_expect + result = self.cpp.process_contents(substitution_input) + assert expect == result, (expect, result) + + def test_ifdef(self): + """Test basic #ifdef processing""" + expect = self.ifdef_expect + result = self.cpp.process_contents(ifdef_input) + assert expect == result, (expect, result) + + def test_if_boolean(self): + """Test #if with Boolean values""" + expect = self.if_boolean_expect + result = self.cpp.process_contents(if_boolean_input) + assert expect == result, (expect, result) + + def test_if_defined(self): + """Test #if defined() idioms""" + expect = self.if_defined_expect + result = self.cpp.process_contents(if_defined_input) + assert expect == result, (expect, result) + + def test_expression(self): + """Test #if with arithmetic expressions""" + expect = self.expression_expect + result = self.cpp.process_contents(expression_input) + assert expect == result, (expect, result) + + def test_undef(self): + """Test #undef handling""" + expect = self.undef_expect + result = self.cpp.process_contents(undef_input) + assert expect == result, (expect, result) + + def test_macro_function(self): + """Test using macro functions to express file names""" + expect = self.macro_function_expect + result = self.cpp.process_contents(macro_function_input) + assert expect == result, (expect, result) + + def test_token_pasting(self): + """Test token-pasting to construct file names""" + expect = self.token_pasting_expect + result = self.cpp.process_contents(token_pasting_input) + assert expect == result, (expect, result) + + def test_no_space(self): + """Test no space between #include and the quote""" + expect = self.no_space_expect + result = self.cpp.process_contents(no_space_input) + assert expect == result, (expect, result) + +class cppAllTestCase(cppTestCase): + def setUp(self): + self.cpp = self.cpp_class(current = ".", + cpppath = ['/usr/include'], + all=1) + +class PreProcessorTestCase(cppAllTestCase): + cpp_class = cpp.PreProcessor + + basic_expect = [ + ('include', '"', 'file1-yes'), + ('include', '<', 'file2-yes'), + ] + + substitution_expect = [ + ('include', '"', 'file3-yes'), + ('include', '<', 'file4-yes'), + ('include', '"', 'file5-yes'), + ('include', '<', 'file6-yes'), + ] + + ifdef_expect = [ + ('include', '"', 'file7-yes'), + ('include', '<', 'file8-yes'), + ] + + if_boolean_expect = [ + ('include', '"', 'file9-yes'), + ('include', '<', 'file10-yes'), + ('include', '"', 'file11-yes'), + ('include', '<', 'file12-yes'), + ('include', '"', 'file13-yes'), + ('include', '<', 'file14-yes'), + ] + + if_defined_expect = [ + ('include', '"', 'file15-yes'), + ('include', '<', 'file16-yes'), + ('include', '"', 'file17-yes'), + ('include', '<', 'file18-yes'), + ] + + expression_expect = [ + ('include', '"', 'file19-yes'), + ('include', '<', 'file20-yes'), + ('include', '"', 'file21-yes'), + ('include', '<', 'file22-yes'), + ('include', '"', 'file23-yes'), + ('include', '<', 'file24-yes'), + ('include', '"', 'file25-yes'), + ('include', '<', 'file26-yes'), + ('include', '"', 'file27-yes'), + ('include', '<', 'file28-yes'), + ('include', '"', 'file29-yes'), + ('include', '<', 'file30-yes'), + ] + + undef_expect = [ + ('include', '"', 'file31-yes'), + ('include', '<', 'file32-yes'), + ] + + macro_function_expect = [ + ('include', '"', 'file33-yes'), + ('include', '<', 'file34-yes'), + ('include', '"', 'file35-yes'), + ('include', '<', 'file36-yes'), + ('include', '"', 'file37-yes'), + ('include', '<', 'file38-yes'), + ('include', '"', 'file39-yes'), + ('include', '<', 'file40-yes'), + ] + + token_pasting_expect = [ + ('include', '"', 'file41-yes'), + ('include', '<', 'file42-yes'), + ] + + no_space_expect = [ + ('include', '<', 'file43-yes'), + ('include', '"', 'file44-yes'), + ] + +class DumbPreProcessorTestCase(cppAllTestCase): + cpp_class = cpp.DumbPreProcessor + + basic_expect = [ + ('include', '"', 'file1-yes'), + ('include', '<', 'file2-yes'), + ] + + substitution_expect = [ + ('include', '"', 'file3-yes'), + ('include', '<', 'file4-yes'), + ('include', '"', 'file5-yes'), + ('include', '<', 'file6-yes'), + ] + + ifdef_expect = [ + ('include', '"', 'file7-yes'), + ('include', '"', 'file7-no'), + ('include', '<', 'file8-no'), + ('include', '<', 'file8-yes'), + ] + + if_boolean_expect = [ + ('include', '"', 'file9-no'), + ('include', '"', 'file9-yes'), + ('include', '<', 'file10-yes'), + ('include', '<', 'file10-no'), + ('include', '"', 'file11-no-1'), + ('include', '"', 'file11-no-2'), + ('include', '"', 'file11-yes'), + ('include', '<', 'file12-no-1'), + ('include', '<', 'file12-yes'), + ('include', '<', 'file12-no-2'), + ('include', '"', 'file13-yes'), + ('include', '"', 'file13-no-1'), + ('include', '"', 'file13-no-2'), + ('include', '<', 'file14-yes'), + ('include', '<', 'file14-no-1'), + ('include', '<', 'file14-no-2'), + ] + + if_defined_expect = [ + ('include', '"', 'file15-yes'), + ('include', '<', 'file16-no'), + ('include', '<', 'file16-yes'), + ('include', '"', 'file17-yes'), + ('include', '<', 'file18-no'), + ('include', '<', 'file18-yes'), + ] + + expression_expect = [ + ('include', '"', 'file19-no'), + ('include', '"', 'file19-yes'), + ('include', '<', 'file20-no'), + ('include', '<', 'file20-yes'), + ('include', '"', 'file21-no'), + ('include', '"', 'file21-yes'), + ('include', '<', 'file22-yes'), + ('include', '<', 'file22-no'), + ('include', '"', 'file23-no'), + ('include', '"', 'file23-yes'), + ('include', '<', 'file24-yes'), + ('include', '<', 'file24-no'), + ('include', '"', 'file25-yes'), + ('include', '"', 'file25-no'), + ('include', '<', 'file26-yes'), + ('include', '<', 'file26-no'), + ('include', '"', 'file27-yes'), + ('include', '"', 'file27-no'), + ('include', '<', 'file28-no'), + ('include', '<', 'file28-yes'), + ('include', '"', 'file29-no'), + ('include', '"', 'file29-yes'), + ('include', '<', 'file30-yes'), + ('include', '<', 'file30-no'), + ] + + undef_expect = [ + ('include', '"', 'file31-yes'), + ('include', '"', 'file31-no'), + ('include', '<', 'file32-no'), + ('include', '<', 'file32-yes'), + ] + + macro_function_expect = [ + ('include', '"', 'file33-yes'), + ('include', '<', 'file34-yes'), + ('include', '"', 'file35-yes'), + ('include', '<', 'file36-yes'), + ('include', '"', 'file37-yes'), + ('include', '<', 'file38-yes'), + ('include', '"', 'file39-yes'), + ('include', '<', 'file40-yes'), + ] + + token_pasting_expect = [ + ('include', '"', 'file41-yes'), + ('include', '<', 'file42-yes'), + ] + + no_space_expect = [ + ('include', '<', 'file43-yes'), + ('include', '"', 'file44-yes'), + ] + + + +import os +import re +import shutil +import tempfile + +tempfile.template = 'cppTests.' +if os.name in ('posix', 'nt'): + tempfile.template = 'cppTests.' + str(os.getpid()) + '.' +else: + tempfile.template = 'cppTests.' + +_Cleanup = [] + +def _clean(): + for dir in _Cleanup: + if os.path.exists(dir): + shutil.rmtree(dir) + +sys.exitfunc = _clean + +class fileTestCase(unittest.TestCase): + cpp_class = cpp.DumbPreProcessor + + def setUp(self): + try: + path = tempfile.mktemp(prefix=tempfile.template) + except TypeError: + # The tempfile.mktemp() function in earlier versions of Python + # has no prefix argument, but uses the tempfile.template + # value that we set above. + path = tempfile.mktemp() + _Cleanup.append(path) + os.mkdir(path) + self.tempdir = path + self.orig_cwd = os.getcwd() + os.chdir(path) + + def tearDown(self): + os.chdir(self.orig_cwd) + shutil.rmtree(self.tempdir) + _Cleanup.remove(self.tempdir) + + def strip_initial_spaces(self, s): + #lines = s.split('\n') + lines = string.split(s, '\n') + spaces = re.match(' *', lines[0]).group(0) + def strip_spaces(l, spaces=spaces): + #if l.startswith(spaces): + if l[:len(spaces)] == spaces: + l = l[len(spaces):] + return l + #return '\n'.join([ strip_spaces(l) for l in lines ]) + return string.join(map(strip_spaces, lines), '\n') + + def write(self, file, contents): + open(file, 'w').write(self.strip_initial_spaces(contents)) + + def test_basic(self): + """Test basic file inclusion""" + self.write('f1.h', """\ + #include "f2.h" + """) + self.write('f2.h', """\ + #include <f3.h> + """) + self.write('f3.h', """\ + """) + p = cpp.DumbPreProcessor(current = os.curdir, + cpppath = [os.curdir]) + result = p('f1.h') + assert result == ['f2.h', 'f3.h'], result + + def test_current_file(self): + """Test use of the .current_file attribute""" + self.write('f1.h', """\ + #include <f2.h> + """) + self.write('f2.h', """\ + #include "f3.h" + """) + self.write('f3.h', """\ + """) + class MyPreProcessor(cpp.DumbPreProcessor): + def __init__(self, *args, **kw): + apply(cpp.DumbPreProcessor.__init__, (self,) + args, kw) + self.files = [] + def __call__(self, file): + self.files.append(file) + return cpp.DumbPreProcessor.__call__(self, file) + def scons_current_file(self, t): + r = cpp.DumbPreProcessor.scons_current_file(self, t) + self.files.append(self.current_file) + return r + p = MyPreProcessor(current = os.curdir, cpppath = [os.curdir]) + result = p('f1.h') + assert result == ['f2.h', 'f3.h'], result + assert p.files == ['f1.h', 'f2.h', 'f3.h', 'f2.h', 'f1.h'], p.files + + + +if __name__ == '__main__': + suite = unittest.TestSuite() + tclasses = [ PreProcessorTestCase, + DumbPreProcessorTestCase, + fileTestCase, + ] + for tclass in tclasses: + names = unittest.getTestCaseNames(tclass, 'test_') + try: + names = list(set(names)) + except NameError: + pass + names.sort() + suite.addTests(map(tclass, names)) + if not unittest.TextTestRunner().run(suite).wasSuccessful(): + sys.exit(1) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: |