Esempio n. 1
0
def main(output, input_file):
    pp = Preprocessor()
    pp.context.update({
        'FFI_EXEC_TRAMPOLINE_TABLE': '0',
        'HAVE_LONG_DOUBLE': '0',
        'TARGET': buildconfig.substs['FFI_TARGET'],
        'VERSION': '',
    })
    pp.do_filter('substitution')
    pp.setMarker(None)
    pp.out = output
    pp.do_include(input_file)
Esempio n. 2
0
def main(output, input_file):
    pp = Preprocessor()
    pp.context.update({
        'FFI_EXEC_TRAMPOLINE_TABLE': '0',
        'HAVE_LONG_DOUBLE': '0',
        'TARGET': buildconfig.substs['FFI_TARGET'],
        'VERSION': '',
    })
    pp.do_filter('substitution')
    pp.setMarker(None)
    pp.out = output
    pp.do_include(input_file)
def main(output, input_file, *defines):
    pp = Preprocessor()
    pp.context.update({
        "FFI_EXEC_TRAMPOLINE_TABLE": "0",
        "HAVE_LONG_DOUBLE": "0",
        "TARGET": buildconfig.substs["FFI_TARGET"],
        "VERSION": "",
    })
    for d in defines:
        pp.context.update({d: "1"})
    pp.do_filter("substitution")
    pp.setMarker(None)
    pp.out = output
    pp.do_include(input_file)
Esempio n. 4
0
def main(output, input_file):
    pp = Preprocessor()
    pp.context.update(
        {
            "FFI_EXEC_TRAMPOLINE_TABLE": "0",
            "HAVE_LONG_DOUBLE": "0",
            "TARGET": buildconfig.substs["FFI_TARGET"],
            "VERSION": "",
        }
    )
    pp.do_filter("substitution")
    pp.setMarker(None)
    pp.out = output
    pp.do_include(input_file)
Esempio n. 5
0
def rnp_preprocess(tmpl, dest, defines):
    """
    Generic preprocessing
    :param BinaryIO tmpl: open filehandle (read) input
    :param BinaryIO dest: open filehandle (write) output
    :param dict defines: result of get_defines()
    :return boolean:
    """
    pp = Preprocessor()
    pp.setMarker("%")
    pp.addDefines(defines)
    pp.do_filter("substitution")
    pp.out = dest
    pp.do_include(tmpl, True)
    return True
Esempio n. 6
0
    def _get_preprocessor(self, output, extra):
        '''Returns a preprocessor for use by create_config_file and
        create_makefile.
        '''
        path = output.name
        pp = Preprocessor()
        pp.context.update(self.substs)
        pp.context.update(top_srcdir = self.get_top_srcdir(path))
        pp.context.update(srcdir = self.get_file_srcdir(path))
        pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
        pp.context.update(DEPTH = self.get_depth(path))
        if extra:
            pp.context.update(extra)
        pp.do_filter('attemptSubstitution')
        pp.setMarker(None)

        pp.out = output
        return pp
Esempio n. 7
0
    def _get_preprocessor(self, output, extra):
        '''Returns a preprocessor for use by create_config_file and
        create_makefile.
        '''
        path = output.name
        pp = Preprocessor()
        pp.context.update(self.substs)
        pp.context.update(top_srcdir=self.get_top_srcdir(path))
        pp.context.update(srcdir=self.get_file_srcdir(path))
        pp.context.update(relativesrcdir=self.get_relative_srcdir(path))
        pp.context.update(DEPTH=self.get_depth(path))
        if extra:
            pp.context.update(extra)
        pp.do_filter('attemptSubstitution')
        pp.setMarker(None)

        pp.out = output
        return pp
Esempio n. 8
0
class TestPreprocessor(unittest.TestCase):
    """
    Unit tests for the Context class
    """
    def setUp(self):
        self.pp = Preprocessor()
        self.pp.out = StringIO()

    def do_include_compare(self, content_lines, expected_lines):
        content = '%s' % '\n'.join(content_lines)
        expected = '%s'.rstrip() % '\n'.join(expected_lines)

        with MockedOpen({'dummy': content}):
            self.pp.do_include('dummy')
            self.assertEqual(self.pp.out.getvalue().rstrip('\n'), expected)

    def do_include_pass(self, content_lines):
        self.do_include_compare(content_lines, ['PASS'])

    def test_conditional_if_0(self):
        self.do_include_pass([
            '#if 0',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_no_marker(self):
        lines = [
            '#if 0',
            'PASS',
            '#endif',
        ]
        self.pp.setMarker(None)
        self.do_include_compare(lines, lines)

    def test_string_value(self):
        self.do_include_compare([
            '#define FOO STRING',
            '#if FOO',
            'string value is true',
            '#else',
            'string value is false',
            '#endif',
        ], ['string value is false'])

    def test_number_value(self):
        self.do_include_compare([
            '#define FOO 1',
            '#if FOO',
            'number value is true',
            '#else',
            'number value is false',
            '#endif',
        ], ['number value is true'])

    def test_conditional_if_0_elif_1(self):
        self.do_include_pass([
            '#if 0',
            '#elif 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_1(self):
        self.do_include_pass([
            '#if 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_0_or_1(self):
        self.do_include_pass([
            '#if 0 || 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_1_elif_1_else(self):
        self.do_include_pass([
            '#if 1',
            'PASS',
            '#elif 1',
            'FAIL',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_1_if_1(self):
        self.do_include_pass([
            '#if 1',
            '#if 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_not_0(self):
        self.do_include_pass([
            '#if !0',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_not_0_and_1(self):
        self.do_include_pass([
            '#if !0 && !1',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_conditional_not_1(self):
        self.do_include_pass([
            '#if !1',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_conditional_not_emptyval(self):
        self.do_include_compare([
            '#define EMPTYVAL',
            '#ifndef EMPTYVAL',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
            '#ifdef EMPTYVAL',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ], ['PASS', 'PASS'])

    def test_conditional_not_nullval(self):
        self.do_include_pass([
            '#define NULLVAL 0',
            '#if !NULLVAL',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_expand(self):
        self.do_include_pass([
            '#define ASVAR AS',
            '#expand P__ASVAR__S',
        ])

    def test_undef_defined(self):
        self.do_include_compare([
            '#define BAR',
            '#undef BAR',
            'BAR',
        ], ['BAR'])

    def test_undef_undefined(self):
        self.do_include_compare([
            '#undef BAR',
        ], [])

    def test_filter_attemptSubstitution(self):
        self.do_include_compare([
            '#filter attemptSubstitution',
            '@PASS@',
            '#unfilter attemptSubstitution',
        ], ['@PASS@'])

    def test_filter_emptyLines(self):
        self.do_include_compare([
            'lines with a',
            '',
            'blank line',
            '#filter emptyLines',
            'lines with',
            '',
            'no blank lines',
            '#unfilter emptyLines',
            'yet more lines with',
            '',
            'blank lines',
        ], [
            'lines with a',
            '',
            'blank line',
            'lines with',
            'no blank lines',
            'yet more lines with',
            '',
            'blank lines',
        ])

    def test_filter_slashslash(self):
        self.do_include_compare([
            '#filter slashslash',
            'PASS//FAIL  // FAIL',
            '#unfilter slashslash',
            'PASS // PASS',
        ], [
            'PASS',
            'PASS // PASS',
        ])

    def test_filter_spaces(self):
        self.do_include_compare([
            '#filter spaces',
            'You should see two nice ascii tables',
            ' +-+-+-+',
            ' | |   |     |',
            ' +-+-+-+',
            '#unfilter spaces',
            '+-+---+',
            '| |   |',
            '+-+---+',
        ], [
            'You should see two nice ascii tables',
            '+-+-+-+',
            '| | | |',
            '+-+-+-+',
            '+-+---+',
            '| |   |',
            '+-+---+',
        ])

    def test_filter_substitution(self):
        self.do_include_pass([
            '#define VAR ASS',
            '#filter substitution',
            'P@VAR@',
            '#unfilter substitution',
        ])

    def test_error(self):
        with MockedOpen({'f': '#error spit this message out\n'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
                self.assertEqual(e.args[0][-1], 'spit this message out')

    def test_javascript_line(self):
        # The preprocessor is reading the filename from somewhere not caught
        # by MockedOpen.
        tmpdir = mkdtemp()
        try:
            full = os.path.join(tmpdir, 'javascript_line.js.in')
            with open(full, 'w') as fh:
                fh.write('\n'.join([
                    '// 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(full)
            out = '\n'.join([
                '// 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', tmpdir + os.path.sep)
            self.assertEqual(self.pp.out.getvalue(), out)
        finally:
            shutil.rmtree(tmpdir)

    def test_literal(self):
        self.do_include_pass([
            '#literal PASS',
        ])

    def test_var_directory(self):
        self.do_include_pass([
            '#ifdef DIRECTORY',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_file(self):
        self.do_include_pass([
            '#ifdef FILE',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_if_0(self):
        self.do_include_pass([
            '#define VAR 0',
            '#if VAR',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_if_0_elifdef(self):
        self.do_include_pass([
            '#if 0',
            '#elifdef FILE',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_if_0_elifndef(self):
        self.do_include_pass([
            '#if 0',
            '#elifndef VAR',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_ifdef_0(self):
        self.do_include_pass([
            '#define VAR 0',
            '#ifdef VAR',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_ifdef_1_or_undef(self):
        self.do_include_pass([
            '#define FOO 1',
            '#if defined(FOO) || defined(BAR)',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_ifdef_undef(self):
        self.do_include_pass([
            '#define VAR 0',
            '#undef VAR',
            '#ifdef VAR',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_ifndef_0(self):
        self.do_include_pass([
            '#define VAR 0',
            '#ifndef VAR',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_ifndef_0_and_undef(self):
        self.do_include_pass([
            '#define FOO 0',
            '#if !defined(FOO) && !defined(BAR)',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_ifndef_undef(self):
        self.do_include_pass([
            '#define VAR 0',
            '#undef VAR',
            '#ifndef VAR',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_line(self):
        self.do_include_pass([
            '#ifdef LINE',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_filterDefine(self):
        self.do_include_pass([
            '#filter substitution',
            '#define VAR AS',
            '#define VAR2 P@VAR@',
            '@VAR2@S',
        ])

    def test_number_value_equals(self):
        self.do_include_pass([
            '#define FOO 1000',
            '#if FOO == 1000',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_default_defines(self):
        self.pp.handleCommandLine(["-DFOO"])
        self.do_include_pass([
            '#if FOO == 1',
            'PASS',
            '#else',
            'FAIL',
        ])

    def test_number_value_equals_defines(self):
        self.pp.handleCommandLine(["-DFOO=1000"])
        self.do_include_pass([
            '#if FOO == 1000',
            'PASS',
            '#else',
            'FAIL',
        ])

    def test_octal_value_equals(self):
        self.do_include_pass([
            '#define FOO 0100',
            '#if FOO == 0100',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_octal_value_equals_defines(self):
        self.pp.handleCommandLine(["-DFOO=0100"])
        self.do_include_pass([
            '#if FOO == 0100',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_value_quoted_expansion(self):
        """
        Quoted values on the commandline don't currently have quotes stripped.
        Pike says this is for compat reasons.
        """
        self.pp.handleCommandLine(['-DFOO="ABCD"'])
        self.do_include_compare([
            '#filter substitution',
            '@FOO@',
        ], ['"ABCD"'])

    def test_octal_value_quoted_expansion(self):
        self.pp.handleCommandLine(['-DFOO="0100"'])
        self.do_include_compare([
            '#filter substitution',
            '@FOO@',
        ], ['"0100"'])

    def test_number_value_not_equals_quoted_defines(self):
        self.pp.handleCommandLine(['-DFOO="1000"'])
        self.do_include_pass([
            '#if FOO == 1000',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_octal_value_not_equals_quoted_defines(self):
        self.pp.handleCommandLine(['-DFOO="0100"'])
        self.do_include_pass([
            '#if FOO == 0100',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_undefined_variable(self):
        with MockedOpen({'f': '#filter substitution\n@foo@'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
                self.assertEqual(e.key, 'UNDEFINED_VAR')

    def test_include(self):
        files = {
            'foo/test':
            '\n'.join([
                '#define foo foobarbaz',
                '#include @inc@',
                '@bar@',
                '',
            ]),
            'bar':
            '\n'.join([
                '#define bar barfoobaz',
                '@foo@',
                '',
            ]),
            'f':
            '\n'.join([
                '#filter substitution',
                '#define inc ../bar',
                '#include foo/test',
                '',
            ]),
        }

        with MockedOpen(files):
            self.pp.do_include('f')
            self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\nbarfoobaz\n')

    def test_include_line(self):
        files = {
            'srcdir/test.js':
            '\n'.join([
                '#define foo foobarbaz',
                '#include @inc@',
                '@bar@',
                '',
            ]),
            'srcdir/bar.js':
            '\n'.join([
                '#define bar barfoobaz',
                '@foo@',
                '',
            ]),
            'srcdir/foo.js':
            '\n'.join([
                'bazfoobar',
                '#include bar.js',
                'bazbarfoo',
                '',
            ]),
            'objdir/baz.js':
            'baz\n',
            'srcdir/f.js':
            '\n'.join([
                '#include foo.js',
                '#filter substitution',
                '#define inc bar.js',
                '#include test.js',
                '#include ../objdir/baz.js',
                'fin',
                '',
            ]),
        }

        preprocessed = ('//@line 1 "$SRCDIR/foo.js"\n'
                        'bazfoobar\n'
                        '//@line 2 "$SRCDIR/bar.js"\n'
                        '@foo@\n'
                        '//@line 3 "$SRCDIR/foo.js"\n'
                        'bazbarfoo\n'
                        '//@line 2 "$SRCDIR/bar.js"\n'
                        'foobarbaz\n'
                        '//@line 3 "$SRCDIR/test.js"\n'
                        'barfoobaz\n'
                        '//@line 1 "$OBJDIR/baz.js"\n'
                        'baz\n'
                        '//@line 6 "$SRCDIR/f.js"\n'
                        'fin\n').replace('DIR/', 'DIR' + os.sep)

        # Try with separate srcdir/objdir
        with MockedOpen(files):
            self.pp.topsrcdir = os.path.abspath('srcdir')
            self.pp.topobjdir = os.path.abspath('objdir')
            self.pp.do_include('srcdir/f.js')
            self.assertEqual(self.pp.out.getvalue(), preprocessed)

        # Try again with relative objdir
        self.setUp()
        files['srcdir/objdir/baz.js'] = files['objdir/baz.js']
        del files['objdir/baz.js']
        files['srcdir/f.js'] = files['srcdir/f.js'].replace('../', '')
        with MockedOpen(files):
            self.pp.topsrcdir = os.path.abspath('srcdir')
            self.pp.topobjdir = os.path.abspath('srcdir/objdir')
            self.pp.do_include('srcdir/f.js')
            self.assertEqual(self.pp.out.getvalue(), preprocessed)

    def test_include_missing_file(self):
        with MockedOpen({'f': '#include foo\n'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
            self.assertEqual(e.exception.key, 'FILE_NOT_FOUND')

    def test_include_undefined_variable(self):
        with MockedOpen({'f': '#filter substitution\n#include @foo@\n'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
            self.assertEqual(e.exception.key, 'UNDEFINED_VAR')

    def test_include_literal_at(self):
        files = {
            '@foo@': '#define foo foobarbaz\n',
            'f': '#include @foo@\n#filter substitution\n@foo@\n',
        }

        with MockedOpen(files):
            self.pp.do_include('f')
            self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')

    def test_command_line_literal_at(self):
        with MockedOpen({"@[email protected]": '@foo@\n'}):
            self.pp.handleCommandLine(
                ['-Fsubstitution', '-Dfoo=foobarbaz', '@[email protected]'])
            self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')

    def test_invalid_ifdef(self):
        with MockedOpen({'dummy': '#ifdef FOO == BAR\nPASS\n#endif'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('dummy')
            self.assertEqual(e.exception.key, 'INVALID_VAR')

        with MockedOpen({'dummy': '#ifndef FOO == BAR\nPASS\n#endif'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('dummy')
            self.assertEqual(e.exception.key, 'INVALID_VAR')

        # Trailing whitespaces, while not nice, shouldn't be an error.
        self.do_include_pass([
            '#ifndef  FOO ',
            'PASS',
            '#endif',
        ])
class TestPreprocessor(unittest.TestCase):
    """
    Unit tests for the Context class
    """

    def setUp(self):
        self.pp = Preprocessor()
        self.pp.out = StringIO()

    def do_include_compare(self, content_lines, expected_lines):
        content = '%s' % '\n'.join(content_lines)
        expected = '%s'.rstrip() % '\n'.join(expected_lines)

        with MockedOpen({'dummy': content}):
            self.pp.do_include('dummy')
            self.assertEqual(self.pp.out.getvalue().rstrip('\n'), expected)

    def do_include_pass(self, content_lines):
        self.do_include_compare(content_lines, ['PASS'])

    def test_conditional_if_0(self):
        self.do_include_pass([
            '#if 0',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_no_marker(self):
        lines = [
            '#if 0',
            'PASS',
            '#endif',
        ]
        self.pp.setMarker(None)
        self.do_include_compare(lines, lines)

    def test_string_value(self):
        self.do_include_compare([
            '#define FOO STRING',
            '#if FOO',
            'string value is true',
            '#else',
            'string value is false',
            '#endif',
        ], ['string value is false'])

    def test_number_value(self):
        self.do_include_compare([
            '#define FOO 1',
            '#if FOO',
            'number value is true',
            '#else',
            'number value is false',
            '#endif',
        ], ['number value is true'])

    def test_conditional_if_0_elif_1(self):
        self.do_include_pass([
            '#if 0',
            '#elif 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_1(self):
        self.do_include_pass([
            '#if 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_0_or_1(self):
        self.do_include_pass([
            '#if 0 || 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_1_elif_1_else(self):
        self.do_include_pass([
            '#if 1',
            'PASS',
            '#elif 1',
            'FAIL',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_if_1_if_1(self):
        self.do_include_pass([
            '#if 1',
            '#if 1',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_not_0(self):
        self.do_include_pass([
            '#if !0',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_conditional_not_0_and_1(self):
        self.do_include_pass([
            '#if !0 && !1',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_conditional_not_1(self):
        self.do_include_pass([
            '#if !1',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_conditional_not_emptyval(self):
        self.do_include_compare([
            '#define EMPTYVAL',
            '#ifndef EMPTYVAL',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
            '#ifdef EMPTYVAL',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ], ['PASS', 'PASS'])

    def test_conditional_not_nullval(self):
        self.do_include_pass([
            '#define NULLVAL 0',
            '#if !NULLVAL',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_expand(self):
        self.do_include_pass([
            '#define ASVAR AS',
            '#expand P__ASVAR__S',
        ])

    def test_undef_defined(self):
        self.do_include_compare([
            '#define BAR',
            '#undef BAR',
            'BAR',
        ], ['BAR'])

    def test_undef_undefined(self):
        self.do_include_compare([
            '#undef BAR',
        ], [])

    def test_filter_attemptSubstitution(self):
        self.do_include_compare([
            '#filter attemptSubstitution',
            '@PASS@',
            '#unfilter attemptSubstitution',
        ], ['@PASS@'])

    def test_filter_emptyLines(self):
        self.do_include_compare([
            'lines with a',
            '',
            'blank line',
            '#filter emptyLines',
            'lines with',
            '',
            'no blank lines',
            '#unfilter emptyLines',
            'yet more lines with',
            '',
            'blank lines',
        ], [
            'lines with a',
            '',
            'blank line',
            'lines with',
            'no blank lines',
            'yet more lines with',
            '',
            'blank lines',
        ])

    def test_filter_slashslash(self):
        self.do_include_compare([
            '#filter slashslash',
            'PASS//FAIL  // FAIL',
            '#unfilter slashslash',
            'PASS // PASS',
        ], [
            'PASS',
            'PASS // PASS',
        ])

    def test_filter_spaces(self):
        self.do_include_compare([
            '#filter spaces',
            'You should see two nice ascii tables',
            ' +-+-+-+',
            ' | |   |     |',
            ' +-+-+-+',
            '#unfilter spaces',
            '+-+---+',
            '| |   |',
            '+-+---+',
        ], [
            'You should see two nice ascii tables',
            '+-+-+-+',
            '| | | |',
            '+-+-+-+',
            '+-+---+',
            '| |   |',
            '+-+---+',
        ])

    def test_filter_substitution(self):
        self.do_include_pass([
            '#define VAR ASS',
            '#filter substitution',
            'P@VAR@',
            '#unfilter substitution',
        ])

    def test_error(self):
        with MockedOpen({'f': '#error spit this message out\n'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
                self.assertEqual(e.args[0][-1], 'spit this message out')

    def test_javascript_line(self):
        # The preprocessor is reading the filename from somewhere not caught
        # by MockedOpen.
        tmpdir = mkdtemp()
        try:
            full = os.path.join(tmpdir, 'javascript_line.js.in')
            with open(full, 'w') as fh:
                fh.write('\n'.join([
                    '// 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(full)
            out = '\n'.join([
                '// 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', tmpdir + os.path.sep)
            self.assertEqual(self.pp.out.getvalue(), out)
        finally:
            shutil.rmtree(tmpdir)

    def test_literal(self):
        self.do_include_pass([
            '#literal PASS',
        ])

    def test_var_directory(self):
        self.do_include_pass([
            '#ifdef DIRECTORY',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_file(self):
        self.do_include_pass([
            '#ifdef FILE',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_if_0(self):
        self.do_include_pass([
            '#define VAR 0',
            '#if VAR',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_if_0_elifdef(self):
        self.do_include_pass([
            '#if 0',
            '#elifdef FILE',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_if_0_elifndef(self):
        self.do_include_pass([
            '#if 0',
            '#elifndef VAR',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_ifdef_0(self):
        self.do_include_pass([
            '#define VAR 0',
            '#ifdef VAR',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_ifdef_1_or_undef(self):
        self.do_include_pass([
            '#define FOO 1',
            '#if defined(FOO) || defined(BAR)',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_ifdef_undef(self):
        self.do_include_pass([
            '#define VAR 0',
            '#undef VAR',
            '#ifdef VAR',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_ifndef_0(self):
        self.do_include_pass([
            '#define VAR 0',
            '#ifndef VAR',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_ifndef_0_and_undef(self):
        self.do_include_pass([
            '#define FOO 0',
            '#if !defined(FOO) && !defined(BAR)',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_var_ifndef_undef(self):
        self.do_include_pass([
            '#define VAR 0',
            '#undef VAR',
            '#ifndef VAR',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_var_line(self):
        self.do_include_pass([
            '#ifdef LINE',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_filterDefine(self):
        self.do_include_pass([
            '#filter substitution',
            '#define VAR AS',
            '#define VAR2 P@VAR@',
            '@VAR2@S',
        ])

    def test_number_value_equals(self):
        self.do_include_pass([
            '#define FOO 1000',
            '#if FOO == 1000',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_default_defines(self):
        self.pp.handleCommandLine(["-DFOO"])
        self.do_include_pass([
            '#if FOO == 1',
            'PASS',
            '#else',
            'FAIL',
        ])

    def test_number_value_equals_defines(self):
        self.pp.handleCommandLine(["-DFOO=1000"])
        self.do_include_pass([
            '#if FOO == 1000',
            'PASS',
            '#else',
            'FAIL',
        ])

    def test_octal_value_equals(self):
        self.do_include_pass([
            '#define FOO 0100',
            '#if FOO == 0100',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_octal_value_equals_defines(self):
        self.pp.handleCommandLine(["-DFOO=0100"])
        self.do_include_pass([
            '#if FOO == 0100',
            'PASS',
            '#else',
            'FAIL',
            '#endif',
        ])

    def test_value_quoted_expansion(self):
        """
        Quoted values on the commandline don't currently have quotes stripped.
        Pike says this is for compat reasons.
        """
        self.pp.handleCommandLine(['-DFOO="ABCD"'])
        self.do_include_compare([
            '#filter substitution',
            '@FOO@',
        ], ['"ABCD"'])

    def test_octal_value_quoted_expansion(self):
        self.pp.handleCommandLine(['-DFOO="0100"'])
        self.do_include_compare([
            '#filter substitution',
            '@FOO@',
        ], ['"0100"'])

    def test_number_value_not_equals_quoted_defines(self):
        self.pp.handleCommandLine(['-DFOO="1000"'])
        self.do_include_pass([
            '#if FOO == 1000',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_octal_value_not_equals_quoted_defines(self):
        self.pp.handleCommandLine(['-DFOO="0100"'])
        self.do_include_pass([
            '#if FOO == 0100',
            'FAIL',
            '#else',
            'PASS',
            '#endif',
        ])

    def test_undefined_variable(self):
        with MockedOpen({'f': '#filter substitution\n@foo@'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
                self.assertEqual(e.key, 'UNDEFINED_VAR')

    def test_include(self):
        files = {
            'foo/test': '\n'.join([
                '#define foo foobarbaz',
                '#include @inc@',
                '@bar@',
                '',
            ]),
            'bar': '\n'.join([
                '#define bar barfoobaz',
                '@foo@',
                '',
            ]),
            'f': '\n'.join([
                '#filter substitution',
                '#define inc ../bar',
                '#include foo/test',
                '',
            ]),
        }

        with MockedOpen(files):
            self.pp.do_include('f')
            self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\nbarfoobaz\n')

    def test_include_line(self):
        files = {
            'test.js': '\n'.join([
                '#define foo foobarbaz',
                '#include @inc@',
                '@bar@',
                '',
            ]),
            'bar.js': '\n'.join([
                '#define bar barfoobaz',
                '@foo@',
                '',
            ]),
            'foo.js': '\n'.join([
                'bazfoobar',
                '#include bar.js',
                'bazbarfoo',
                '',
            ]),
            'baz.js': 'baz\n',
            'f.js': '\n'.join([
                '#include foo.js',
                '#filter substitution',
                '#define inc bar.js',
                '#include test.js',
                '#include baz.js',
                'fin',
                '',
            ]),
        }

        with MockedOpen(files):
            self.pp.do_include('f.js')
            self.assertEqual(self.pp.out.getvalue(),
                             ('//@line 1 "CWD/foo.js"\n'
                              'bazfoobar\n'
                              '//@line 2 "CWD/bar.js"\n'
                              '@foo@\n'
                              '//@line 3 "CWD/foo.js"\n'
                              'bazbarfoo\n'
                              '//@line 2 "CWD/bar.js"\n'
                              'foobarbaz\n'
                              '//@line 3 "CWD/test.js"\n'
                              'barfoobaz\n'
                              '//@line 1 "CWD/baz.js"\n'
                              'baz\n'
                              '//@line 6 "CWD/f.js"\n'
                              'fin\n').replace('CWD/',
                                               os.getcwd() + os.path.sep))

    def test_include_missing_file(self):
        with MockedOpen({'f': '#include foo\n'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
            self.assertEqual(e.exception.key, 'FILE_NOT_FOUND')

    def test_include_undefined_variable(self):
        with MockedOpen({'f': '#filter substitution\n#include @foo@\n'}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include('f')
            self.assertEqual(e.exception.key, 'UNDEFINED_VAR')

    def test_include_literal_at(self):
        files = {
            '@foo@': '#define foo foobarbaz\n',
            'f': '#include @foo@\n#filter substitution\n@foo@\n',
        }

        with MockedOpen(files):
            self.pp.do_include('f')
            self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')

    def test_command_line_literal_at(self):
        with MockedOpen({"@[email protected]": '@foo@\n'}):
            self.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@[email protected]'])
            self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')
Esempio n. 10
0
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_no_marker(self):
    no_marker = """#if 0
PASS
#endif
"""
    f = NamedIO("no_marker.in", no_marker)
    self.pp.setMarker(None)
    self.pp.do_include(f)
    self.assertEqual(self.pp.out.getvalue(), no_marker)

  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
@PASS@
#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')
Esempio n. 11
0
class TestPreprocessor(unittest.TestCase):
    """
    Unit tests for the Context class
    """
    def setUp(self):
        self.pp = Preprocessor()
        self.pp.out = StringIO()

    def do_include_compare(self, content_lines, expected_lines):
        content = "%s" % "\n".join(content_lines)
        expected = "%s".rstrip() % "\n".join(expected_lines)

        with MockedOpen({"dummy": content}):
            self.pp.do_include("dummy")
            self.assertEqual(self.pp.out.getvalue().rstrip("\n"), expected)

    def do_include_pass(self, content_lines):
        self.do_include_compare(content_lines, ["PASS"])

    def test_conditional_if_0(self):
        self.do_include_pass([
            "#if 0",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_no_marker(self):
        lines = [
            "#if 0",
            "PASS",
            "#endif",
        ]
        self.pp.setMarker(None)
        self.do_include_compare(lines, lines)

    def test_string_value(self):
        self.do_include_compare(
            [
                "#define FOO STRING",
                "#if FOO",
                "string value is true",
                "#else",
                "string value is false",
                "#endif",
            ],
            ["string value is false"],
        )

    def test_number_value(self):
        self.do_include_compare(
            [
                "#define FOO 1",
                "#if FOO",
                "number value is true",
                "#else",
                "number value is false",
                "#endif",
            ],
            ["number value is true"],
        )

    def test_conditional_if_0_elif_1(self):
        self.do_include_pass([
            "#if 0",
            "#elif 1",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_conditional_if_1(self):
        self.do_include_pass([
            "#if 1",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_conditional_if_0_or_1(self):
        self.do_include_pass([
            "#if 0 || 1",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_conditional_if_1_elif_1_else(self):
        self.do_include_pass([
            "#if 1",
            "PASS",
            "#elif 1",
            "FAIL",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_conditional_if_1_if_1(self):
        self.do_include_pass([
            "#if 1",
            "#if 1",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_conditional_not_0(self):
        self.do_include_pass([
            "#if !0",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_conditional_not_0_and_1(self):
        self.do_include_pass([
            "#if !0 && !1",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_conditional_not_1(self):
        self.do_include_pass([
            "#if !1",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_conditional_not_emptyval(self):
        self.do_include_compare(
            [
                "#define EMPTYVAL",
                "#ifndef EMPTYVAL",
                "FAIL",
                "#else",
                "PASS",
                "#endif",
                "#ifdef EMPTYVAL",
                "PASS",
                "#else",
                "FAIL",
                "#endif",
            ],
            ["PASS", "PASS"],
        )

    def test_conditional_not_nullval(self):
        self.do_include_pass([
            "#define NULLVAL 0",
            "#if !NULLVAL",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_indentation(self):
        self.do_include_pass([
            "         #define NULLVAL 0",
            " #if !NULLVAL",
            "PASS",
            "           #else",
            "FAIL",
            "     #endif",
        ])

    def test_expand(self):
        self.do_include_pass([
            "#define ASVAR AS",
            "#expand P__ASVAR__S",
        ])

    def test_undef_defined(self):
        self.do_include_compare(
            [
                "#define BAR",
                "#undef BAR",
                "BAR",
            ],
            ["BAR"],
        )

    def test_undef_undefined(self):
        self.do_include_compare(
            [
                "#undef BAR",
            ],
            [],
        )

    def test_filter_attemptSubstitution(self):
        self.do_include_compare(
            [
                "#filter attemptSubstitution",
                "@PASS@",
                "#unfilter attemptSubstitution",
            ],
            ["@PASS@"],
        )

    def test_filter_emptyLines(self):
        self.do_include_compare(
            [
                "lines with a",
                "",
                "blank line",
                "#filter emptyLines",
                "lines with",
                "",
                "no blank lines",
                "#unfilter emptyLines",
                "yet more lines with",
                "",
                "blank lines",
            ],
            [
                "lines with a",
                "",
                "blank line",
                "lines with",
                "no blank lines",
                "yet more lines with",
                "",
                "blank lines",
            ],
        )

    def test_filter_dumbComments(self):
        self.do_include_compare(
            [
                "#filter dumbComments",
                "PASS//PASS  // PASS",
                "  //FAIL",
                "//     FAIL",
                "PASS  //",
                "PASS  //    FAIL",
                "//",
                "",
                "#unfilter dumbComments",
                "// PASS",
            ],
            [
                "PASS//PASS  // PASS",
                "",
                "",
                "PASS  //",
                "PASS  //    FAIL",
                "",
                "",
                "// PASS",
            ],
        )

    def test_filter_dumbComments_and_emptyLines(self):
        self.do_include_compare(
            [
                "#filter dumbComments emptyLines",
                "PASS//PASS  // PASS",
                "  //FAIL",
                "//     FAIL",
                "PASS  //",
                "PASS  //    FAIL",
                "//",
                "",
                "#unfilter dumbComments emptyLines",
                "",
                "// PASS",
            ],
            [
                "PASS//PASS  // PASS",
                "PASS  //",
                "PASS  //    FAIL",
                "",
                "// PASS",
            ],
        )

    def test_filter_substitution(self):
        self.do_include_pass([
            "#define VAR ASS",
            "#filter substitution",
            "P@VAR@",
            "#unfilter substitution",
        ])

    def test_error(self):
        with MockedOpen({"f": "#error spit this message out\n"}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include("f")
                self.assertEqual(e.args[0][-1], "spit this message out")

    def test_javascript_line(self):
        # The preprocessor is reading the filename from somewhere not caught
        # by MockedOpen.
        tmpdir = mkdtemp()
        try:
            full = os.path.join(tmpdir, "javascript_line.js.in")
            with open(full, "w") as fh:
                fh.write("\n".join([
                    "// 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(full)
            out = "\n".join([
                "// 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", tmpdir + os.path.sep)
            self.assertEqual(self.pp.out.getvalue(), out)
        finally:
            shutil.rmtree(tmpdir)

    def test_literal(self):
        self.do_include_pass([
            "#literal PASS",
        ])

    def test_var_directory(self):
        self.do_include_pass([
            "#ifdef DIRECTORY",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_var_file(self):
        self.do_include_pass([
            "#ifdef FILE",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_var_if_0(self):
        self.do_include_pass([
            "#define VAR 0",
            "#if VAR",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_var_if_0_elifdef(self):
        self.do_include_pass([
            "#if 0",
            "#elifdef FILE",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_var_if_0_elifndef(self):
        self.do_include_pass([
            "#if 0",
            "#elifndef VAR",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_var_ifdef_0(self):
        self.do_include_pass([
            "#define VAR 0",
            "#ifdef VAR",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_var_ifdef_1_or_undef(self):
        self.do_include_pass([
            "#define FOO 1",
            "#if defined(FOO) || defined(BAR)",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_var_ifdef_undef(self):
        self.do_include_pass([
            "#define VAR 0",
            "#undef VAR",
            "#ifdef VAR",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_var_ifndef_0(self):
        self.do_include_pass([
            "#define VAR 0",
            "#ifndef VAR",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_var_ifndef_0_and_undef(self):
        self.do_include_pass([
            "#define FOO 0",
            "#if !defined(FOO) && !defined(BAR)",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_var_ifndef_undef(self):
        self.do_include_pass([
            "#define VAR 0",
            "#undef VAR",
            "#ifndef VAR",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_var_line(self):
        self.do_include_pass([
            "#ifdef LINE",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_filterDefine(self):
        self.do_include_pass([
            "#filter substitution",
            "#define VAR AS",
            "#define VAR2 P@VAR@",
            "@VAR2@S",
        ])

    def test_number_value_equals(self):
        self.do_include_pass([
            "#define FOO 1000",
            "#if FOO == 1000",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_default_defines(self):
        self.pp.handleCommandLine(["-DFOO"])
        self.do_include_pass([
            "#if FOO == 1",
            "PASS",
            "#else",
            "FAIL",
        ])

    def test_number_value_equals_defines(self):
        self.pp.handleCommandLine(["-DFOO=1000"])
        self.do_include_pass([
            "#if FOO == 1000",
            "PASS",
            "#else",
            "FAIL",
        ])

    def test_octal_value_equals(self):
        self.do_include_pass([
            "#define FOO 0100",
            "#if FOO == 0100",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_octal_value_equals_defines(self):
        self.pp.handleCommandLine(["-DFOO=0100"])
        self.do_include_pass([
            "#if FOO == 0100",
            "PASS",
            "#else",
            "FAIL",
            "#endif",
        ])

    def test_value_quoted_expansion(self):
        """
        Quoted values on the commandline don't currently have quotes stripped.
        Pike says this is for compat reasons.
        """
        self.pp.handleCommandLine(['-DFOO="ABCD"'])
        self.do_include_compare(
            [
                "#filter substitution",
                "@FOO@",
            ],
            ['"ABCD"'],
        )

    def test_octal_value_quoted_expansion(self):
        self.pp.handleCommandLine(['-DFOO="0100"'])
        self.do_include_compare(
            [
                "#filter substitution",
                "@FOO@",
            ],
            ['"0100"'],
        )

    def test_number_value_not_equals_quoted_defines(self):
        self.pp.handleCommandLine(['-DFOO="1000"'])
        self.do_include_pass([
            "#if FOO == 1000",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_octal_value_not_equals_quoted_defines(self):
        self.pp.handleCommandLine(['-DFOO="0100"'])
        self.do_include_pass([
            "#if FOO == 0100",
            "FAIL",
            "#else",
            "PASS",
            "#endif",
        ])

    def test_undefined_variable(self):
        with MockedOpen({"f": "#filter substitution\n@foo@"}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include("f")
                self.assertEqual(e.key, "UNDEFINED_VAR")

    def test_include(self):
        files = {
            "foo/test":
            "\n".join([
                "#define foo foobarbaz",
                "#include @inc@",
                "@bar@",
                "",
            ]),
            "bar":
            "\n".join([
                "#define bar barfoobaz",
                "@foo@",
                "",
            ]),
            "f":
            "\n".join([
                "#filter substitution",
                "#define inc ../bar",
                "#include foo/test",
                "",
            ]),
        }

        with MockedOpen(files):
            self.pp.do_include("f")
            self.assertEqual(self.pp.out.getvalue(), "foobarbaz\nbarfoobaz\n")

    def test_include_line(self):
        files = {
            "srcdir/test.js":
            "\n".join([
                "#define foo foobarbaz",
                "#include @inc@",
                "@bar@",
                "",
            ]),
            "srcdir/bar.js":
            "\n".join([
                "#define bar barfoobaz",
                "@foo@",
                "",
            ]),
            "srcdir/foo.js":
            "\n".join([
                "bazfoobar",
                "#include bar.js",
                "bazbarfoo",
                "",
            ]),
            "objdir/baz.js":
            "baz\n",
            "srcdir/f.js":
            "\n".join([
                "#include foo.js",
                "#filter substitution",
                "#define inc bar.js",
                "#include test.js",
                "#include ../objdir/baz.js",
                "fin",
                "",
            ]),
        }

        preprocessed = ('//@line 1 "$SRCDIR/foo.js"\n'
                        "bazfoobar\n"
                        '//@line 2 "$SRCDIR/bar.js"\n'
                        "@foo@\n"
                        '//@line 3 "$SRCDIR/foo.js"\n'
                        "bazbarfoo\n"
                        '//@line 2 "$SRCDIR/bar.js"\n'
                        "foobarbaz\n"
                        '//@line 3 "$SRCDIR/test.js"\n'
                        "barfoobaz\n"
                        '//@line 1 "$OBJDIR/baz.js"\n'
                        "baz\n"
                        '//@line 6 "$SRCDIR/f.js"\n'
                        "fin\n")

        # Try with separate srcdir/objdir
        with MockedOpen(files):
            self.pp.topsrcdir = os.path.abspath("srcdir")
            self.pp.topobjdir = os.path.abspath("objdir")
            self.pp.do_include("srcdir/f.js")
            self.assertEqual(self.pp.out.getvalue(), preprocessed)

        # Try again with relative objdir
        self.setUp()
        files["srcdir/objdir/baz.js"] = files["objdir/baz.js"]
        del files["objdir/baz.js"]
        files["srcdir/f.js"] = files["srcdir/f.js"].replace("../", "")
        with MockedOpen(files):
            self.pp.topsrcdir = os.path.abspath("srcdir")
            self.pp.topobjdir = os.path.abspath("srcdir/objdir")
            self.pp.do_include("srcdir/f.js")
            self.assertEqual(self.pp.out.getvalue(), preprocessed)

    def test_include_missing_file(self):
        with MockedOpen({"f": "#include foo\n"}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include("f")
            self.assertEqual(e.exception.key, "FILE_NOT_FOUND")

    def test_include_undefined_variable(self):
        with MockedOpen({"f": "#filter substitution\n#include @foo@\n"}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include("f")
            self.assertEqual(e.exception.key, "UNDEFINED_VAR")

    def test_include_literal_at(self):
        files = {
            "@foo@": "#define foo foobarbaz\n",
            "f": "#include @foo@\n#filter substitution\n@foo@\n",
        }

        with MockedOpen(files):
            self.pp.do_include("f")
            self.assertEqual(self.pp.out.getvalue(), "foobarbaz\n")

    def test_command_line_literal_at(self):
        with MockedOpen({"@[email protected]": "@foo@\n"}):
            self.pp.handleCommandLine(
                ["-Fsubstitution", "-Dfoo=foobarbaz", "@[email protected]"])
            self.assertEqual(self.pp.out.getvalue(), "foobarbaz\n")

    def test_invalid_ifdef(self):
        with MockedOpen({"dummy": "#ifdef FOO == BAR\nPASS\n#endif"}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include("dummy")
            self.assertEqual(e.exception.key, "INVALID_VAR")

        with MockedOpen({"dummy": "#ifndef FOO == BAR\nPASS\n#endif"}):
            with self.assertRaises(Preprocessor.Error) as e:
                self.pp.do_include("dummy")
            self.assertEqual(e.exception.key, "INVALID_VAR")

        # Trailing whitespaces, while not nice, shouldn't be an error.
        self.do_include_pass([
            "#ifndef  FOO ",
            "PASS",
            "#endif",
        ])