зеркало из https://github.com/mozilla/gecko-dev.git
596 строки
14 KiB
Python
596 строки
14 KiB
Python
from __future__ import with_statement
|
|
import unittest
|
|
|
|
from StringIO import StringIO
|
|
import os
|
|
import sys
|
|
import os.path
|
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
|
|
|
from Preprocessor import Preprocessor
|
|
|
|
class NamedIO(StringIO):
|
|
def __init__(self, name, content):
|
|
self.name = name
|
|
StringIO.__init__(self, content)
|
|
|
|
class MockedOpen(object):
|
|
"""
|
|
Context manager diverting the open builtin such that opening files
|
|
can open NamedIO instances given when creating a MockedOpen.
|
|
|
|
with MockedOpen(NamedIO('foo', 'foo'), NamedIO('bar', 'bar')):
|
|
f = open('foo', 'r')
|
|
|
|
will thus assign the NamedIO instance for the file 'foo' to f.
|
|
"""
|
|
def __init__(self, *files):
|
|
self.files = {}
|
|
for f in files:
|
|
self.files[os.path.abspath(f.name)] = f
|
|
def __call__(self, name, args):
|
|
absname = os.path.abspath(name)
|
|
if absname in self.files:
|
|
return self.files[absname]
|
|
return self.open(name, args)
|
|
def __enter__(self):
|
|
import __builtin__
|
|
self.open = __builtin__.open
|
|
__builtin__.open = self
|
|
def __exit__(self, type, value, traceback):
|
|
import __builtin__
|
|
__builtin__.open = self.open
|
|
|
|
class TestPreprocessor(unittest.TestCase):
|
|
"""
|
|
Unit tests for the Context class
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.pp = Preprocessor()
|
|
self.pp.out = StringIO()
|
|
|
|
def test_conditional_if_0(self):
|
|
f = NamedIO("conditional_if_0.in", """#if 0
|
|
FAIL
|
|
#else
|
|
PASS
|
|
#endif
|
|
""")
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_string_value(self):
|
|
f = NamedIO("string_value.in", """#define FOO STRING
|
|
#if FOO
|
|
string value is true
|
|
#else
|
|
string value is false
|
|
#endif
|
|
""")
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "string value is false\n")
|
|
|
|
def test_number_value(self):
|
|
f = NamedIO("string_value.in", """#define FOO 1
|
|
#if FOO
|
|
number value is true
|
|
#else
|
|
number value is false
|
|
#endif
|
|
""")
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "number value is true\n")
|
|
|
|
def test_conditional_if_0_elif_1(self):
|
|
f = NamedIO('conditional_if_0_elif_1.in', '''#if 0
|
|
#elif 1
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_conditional_if_1(self):
|
|
f = NamedIO('conditional_if_1.in', '''#if 1
|
|
PASS
|
|
#else
|
|
FAILE
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_conditional_if_1_elif_1_else(self):
|
|
f = NamedIO('conditional_if_1_elif_1_else.in', '''#if 1
|
|
PASS
|
|
#elif 1
|
|
FAIL
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_conditional_if_1_if_1(self):
|
|
f = NamedIO('conditional_if_1_if_1.in', '''#if 1
|
|
#if 1
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_conditional_not_0(self):
|
|
f = NamedIO('conditional_not_0.in', '''#if !0
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_conditional_not_1(self):
|
|
f = NamedIO('conditional_not_1.in', '''#if !1
|
|
FAIL
|
|
#else
|
|
PASS
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_conditional_not_emptyval(self):
|
|
f = NamedIO('conditional_not_emptyval.in', '''#define EMPTYVAL
|
|
#if !EMPTYVAL
|
|
FAIL
|
|
#else
|
|
PASS
|
|
#endif
|
|
#if EMPTYVAL
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\nPASS\n")
|
|
|
|
def test_conditional_not_nullval(self):
|
|
f = NamedIO('conditional_not_nullval.in', '''#define NULLVAL 0
|
|
#if !NULLVAL
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_expand(self):
|
|
f = NamedIO('expand.in', '''#define ASVAR AS
|
|
#expand P__ASVAR__S
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_undef_defined(self):
|
|
f = NamedIO('undef_defined.in', '''#define BAR
|
|
#undef BAR
|
|
BAR
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "BAR\n")
|
|
|
|
def test_undef_undefined(self):
|
|
f = NamedIO('undef_undefined.in', '''#undef VAR
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "")
|
|
|
|
def test_filter_attemptSubstitution(self):
|
|
f = NamedIO('filter_attemptSubstitution.in', '''#filter attemptSubstitution
|
|
P@VAR@ASS
|
|
#unfilter attemptSubstitution
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_filter_emptyLines(self):
|
|
f = NamedIO('filter_emptyLines.in', '''lines with a
|
|
|
|
blank line
|
|
#filter emptyLines
|
|
lines with
|
|
|
|
no blank lines
|
|
#unfilter emptyLines
|
|
yet more lines with
|
|
|
|
blank lines
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), '''lines with a
|
|
|
|
blank line
|
|
lines with
|
|
no blank lines
|
|
yet more lines with
|
|
|
|
blank lines
|
|
''')
|
|
|
|
def test_filter_slashslash(self):
|
|
f = NamedIO('filter_slashslash.in', '''#filter slashslash
|
|
PASS//FAIL // FAIL
|
|
#unfilter slashslash
|
|
PASS // PASS
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\nPASS // PASS\n")
|
|
|
|
def test_filter_spaces(self):
|
|
f = NamedIO('filter_spaces.in', '''#filter spaces
|
|
You should see two nice ascii tables
|
|
+-+-+-+
|
|
| | | |
|
|
+-+-+-+
|
|
#unfilter spaces
|
|
+-+---+
|
|
| | |
|
|
+-+---+
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), """You should see two nice ascii tables
|
|
+-+-+-+
|
|
| | | |
|
|
+-+-+-+
|
|
+-+---+
|
|
| | |
|
|
+-+---+
|
|
""")
|
|
|
|
def test_filter_substitution(self):
|
|
f = NamedIO('filter_substitution.in', '''#define VAR ASS
|
|
#filter substitution
|
|
P@VAR@
|
|
#unfilter substitution
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_error(self):
|
|
f = NamedIO('error.in', '''#error spit this message out
|
|
''')
|
|
caught_msg = None
|
|
try:
|
|
self.pp.do_include(f)
|
|
except Preprocessor.Error, e:
|
|
caught_msg = e.args[0][-1]
|
|
self.assertEqual(caught_msg, 'spit this message out')
|
|
|
|
def test_javascript_line(self):
|
|
f = NamedIO('javascript_line.js.in', '''// Line 1
|
|
#if 0
|
|
// line 3
|
|
#endif
|
|
// line 5
|
|
# comment
|
|
// line 7
|
|
// line 8
|
|
// line 9
|
|
# another comment
|
|
// line 11
|
|
#define LINE 1
|
|
// line 13, given line number overwritten with 2
|
|
''')
|
|
self.pp.do_include(f)
|
|
out = """// Line 1
|
|
//@line 5 "CWDjavascript_line.js.in"
|
|
// line 5
|
|
//@line 7 "CWDjavascript_line.js.in"
|
|
// line 7
|
|
// line 8
|
|
// line 9
|
|
//@line 11 "CWDjavascript_line.js.in"
|
|
// line 11
|
|
//@line 2 "CWDjavascript_line.js.in"
|
|
// line 13, given line number overwritten with 2
|
|
"""
|
|
out = out.replace('CWD', os.getcwd() + os.path.sep)
|
|
self.assertEqual(self.pp.out.getvalue(), out)
|
|
|
|
def test_literal(self):
|
|
f = NamedIO('literal.in', '''#literal PASS
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_directory(self):
|
|
f = NamedIO('var_directory.in', '''#ifdef DIRECTORY
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_file(self):
|
|
f = NamedIO('var_file.in', '''#ifdef FILE
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_if_0(self):
|
|
f = NamedIO('var_if_0.in', '''#define VAR 0
|
|
#if VAR
|
|
FAIL
|
|
#else
|
|
PASS
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_if_0_elifdef(self):
|
|
f = NamedIO('var_if_0_elifdef.in', '''#if 0
|
|
#elifdef FILE
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_if_0_elifndef(self):
|
|
f = NamedIO('var_if_0_elifndef.in', '''#if 0
|
|
#elifndef VAR
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_ifdef_0(self):
|
|
f = NamedIO('var_ifdef_0.in', '''#define VAR 0
|
|
#ifdef VAR
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_ifdef_undef(self):
|
|
f = NamedIO('var_ifdef_undef.in', '''#define VAR 0
|
|
#undef VAR
|
|
#ifdef VAR
|
|
FAIL
|
|
#else
|
|
PASS
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_ifndef_0(self):
|
|
f = NamedIO('var_ifndef_0.in', '''#define VAR 0
|
|
#ifndef VAR
|
|
FAIL
|
|
#else
|
|
PASS
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_ifndef_undef(self):
|
|
f = NamedIO('var_ifndef_undef.in', '''#define VAR 0
|
|
#undef VAR
|
|
#ifndef VAR
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_var_line(self):
|
|
f = NamedIO('var_line.in', '''#ifdef LINE
|
|
PASS
|
|
#else
|
|
FAIL
|
|
#endif
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_lineEndings(self):
|
|
f = NamedIO('lineEndings.in', '''first
|
|
#literal second
|
|
''')
|
|
self.pp.setLineEndings('cr')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "first\rsecond\r")
|
|
|
|
def test_filterDefine(self):
|
|
f = NamedIO('filterDefine.in', '''#filter substitution
|
|
#define VAR AS
|
|
#define VAR2 P@VAR@
|
|
@VAR2@S
|
|
''')
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "PASS\n")
|
|
|
|
def test_number_value_equals(self):
|
|
f = NamedIO("number_value_equals.in", """#define FOO 1000
|
|
#if FOO == 1000
|
|
number value is equal
|
|
#else
|
|
number value is not equal
|
|
#endif
|
|
""")
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "number value is equal\n")
|
|
|
|
def test_number_value_equals_defines(self):
|
|
f = NamedIO("number_value_equals_defines.in", """#if FOO == 1000
|
|
number value is equal
|
|
#else
|
|
number value is not equal
|
|
#endif
|
|
""")
|
|
self.pp.handleCommandLine(["-DFOO=1000"])
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "number value is equal\n")
|
|
|
|
def test_octal_value_equals(self):
|
|
f = NamedIO("octal_value_equals.in", """#define FOO 0100
|
|
#if FOO == 0100
|
|
octal value is equal
|
|
#else
|
|
octal value is not equal
|
|
#endif
|
|
""")
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "octal value is equal\n")
|
|
|
|
def test_octal_value_equals_defines(self):
|
|
f = NamedIO("octal_value_equals_defines.in", """#if FOO == 0100
|
|
octal value is equal
|
|
#else
|
|
octal value is not equal
|
|
#endif
|
|
""")
|
|
self.pp.handleCommandLine(["-DFOO=0100"])
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "octal value is equal\n")
|
|
|
|
def test_value_quoted_expansion(self):
|
|
"""
|
|
Quoted values on the commandline don't currently have quotes stripped.
|
|
Pike says this is for compat reasons.
|
|
"""
|
|
f = NamedIO("value_quoted_expansion.in", """#filter substitution
|
|
@FOO@
|
|
""")
|
|
self.pp.handleCommandLine(['-DFOO="ABCD"'])
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), '"ABCD"\n')
|
|
|
|
def test_octal_value_quoted_expansion(self):
|
|
f = NamedIO("value_quoted_expansion.in", """#filter substitution
|
|
@FOO@
|
|
""")
|
|
self.pp.handleCommandLine(['-DFOO="0100"'])
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), '"0100"\n')
|
|
|
|
def test_number_value_not_equals_quoted_defines(self):
|
|
f = NamedIO("number_value_not_equals_quoted_defines.in", """#if FOO == 1000
|
|
number value is equal
|
|
#else
|
|
number value is not equal
|
|
#endif
|
|
""")
|
|
self.pp.handleCommandLine(['-DFOO="1000"'])
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "number value is not equal\n")
|
|
|
|
def test_octal_value_not_equals_quoted_defines(self):
|
|
f = NamedIO("octal_value_not_equals_quoted_defines.in", """#if FOO == 0100
|
|
octal value is equal
|
|
#else
|
|
octal value is not equal
|
|
#endif
|
|
""")
|
|
self.pp.handleCommandLine(['-DFOO="0100"'])
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), "octal value is not equal\n")
|
|
|
|
def test_undefined_variable(self):
|
|
f = NamedIO("undefined_variable.in", """#filter substitution
|
|
@foo@
|
|
""")
|
|
try:
|
|
self.pp.do_include(f)
|
|
except Preprocessor.Error, exception:
|
|
self.assertEqual(exception.key, 'UNDEFINED_VAR')
|
|
else:
|
|
self.fail("Expected a Preprocessor.Error")
|
|
|
|
def test_include(self):
|
|
with MockedOpen(NamedIO("foo/test", """#define foo foobarbaz
|
|
#include @inc@
|
|
@bar@
|
|
"""),
|
|
NamedIO("bar", """#define bar barfoobaz
|
|
@foo@
|
|
""")):
|
|
f = NamedIO("include.in", """#filter substitution
|
|
#define inc ../bar
|
|
#include foo/test""")
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
|
|
barfoobaz
|
|
""")
|
|
|
|
def test_include_missing_file(self):
|
|
f = NamedIO("include_missing_file.in", "#include foo")
|
|
try:
|
|
self.pp.do_include(f)
|
|
except Preprocessor.Error, exception:
|
|
self.assertEqual(exception.key, 'FILE_NOT_FOUND')
|
|
else:
|
|
self.fail("Expected a Preprocessor.Error")
|
|
|
|
def test_include_undefined_variable(self):
|
|
f = NamedIO("include_undefined_variable.in", """#filter substitution
|
|
#include @foo@
|
|
""")
|
|
try:
|
|
self.pp.do_include(f)
|
|
except Preprocessor.Error, exception:
|
|
self.assertEqual(exception.key, 'UNDEFINED_VAR')
|
|
else:
|
|
self.fail("Expected a Preprocessor.Error")
|
|
|
|
def test_include_literal_at(self):
|
|
with MockedOpen(NamedIO("@foo@", "#define foo foobarbaz")):
|
|
f = NamedIO("include_literal_at.in", """#include @foo@
|
|
#filter substitution
|
|
@foo@
|
|
""")
|
|
self.pp.do_include(f)
|
|
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
|
|
""")
|
|
|
|
def test_command_line_literal_at(self):
|
|
with MockedOpen(NamedIO("@foo@.in", """@foo@
|
|
""")):
|
|
self.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@foo@.in'])
|
|
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
|
|
""")
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|