Author: Armin Rigo <ar...@tunes.org> Branch: cmacros Changeset: r2300:33acd0dc850c Date: 2015-10-04 19:04 +0200 http://bitbucket.org/cffi/cffi/changeset/33acd0dc850c/
Log: A bunch of test about how it should be possible to support this: conditional typedefs that used later in the cdef() diff --git a/testing/cffi0/test_parsing.py b/testing/cffi0/test_parsing.py --- a/testing/cffi0/test_parsing.py +++ b/testing/cffi0/test_parsing.py @@ -392,6 +392,254 @@ assert m.BCD == 43 assert m.CDE == 39 +def test_ifdef_partial_unsupported(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + int foo(int + #ifdef ABC + , long + #endif + ); + """) + should_crash + +def test_conditional_typedef_1(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #endif + """) + case = ffi._parser._declarations['typedef foo_t'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert str(case.iftrue) == '<int>' + assert case.iffalse is None + +def test_conditional_typedef_2(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #else + typedef long foo_t; + #endif + """) + case = ffi._parser._declarations['typedef foo_t'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert str(case.iftrue) == '<int>' + assert str(case.iffalse) == '<long>' + +def test_conditional_typedef_3(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + #else + typedef long foo_t; + #endif + """) + case = ffi._parser._declarations['typedef foo_t'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert case.iftrue is None + assert str(case.iffalse) == '<long>' + +def test_conditional_typedef_4(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifndef ABC + typedef long foo_t; + #endif + """) + case = ffi._parser._declarations['typedef foo_t'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert case.iftrue is None + assert str(case.iffalse) == '<long>' + +def test_conditional_func(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifndef ABC + int foo(int); + #endif + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert case.iftrue is None + assert str(case.iffalse) == '<func (<int>), <int>, False>' + +def test_conditional_typedef_used_by_typedef(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #else + typedef long foo_t; + #endif + typedef foo_t bar_t[2]; + """) + case = ffi._parser._declarations['typedef bar_t'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert str(case.iftrue) == '<array <int> x 2>' + assert str(case.iffalse) == '<array <long> x 2>' + +def test_conditional_typedef_used_by_func_1(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #else + typedef long foo_t; + #endif + char foo(foo_t); + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert str(case.iftrue) == '<func (<int>), <char>, False>' + assert str(case.iffalse) == '<func (<long>), <char>, False>' + +def test_conditional_typedef_used_by_func_2(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #else + typedef long foo_t; + #endif + foo_t foo(char); + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert str(case.iftrue) == '<func (<char>), <int>, False>' + assert str(case.iffalse) == '<func (<char>), <long>, False>' + +def test_conditional_typedef_not_used_by_func(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #else + typedef long foo_t; + #endif + char foo(char); + """) + case = ffi._parser._declarations['function foo'] + assert str(case) == '<func (<char>), <char>, False>' + +def test_conditional_nested(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + # if D > E + typedef int foo_t; + # else + typedef unsigned int foo_t; + # endif + #else + typedef long foo_t; + #endif + foo_t foo(char); + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert case.iftrue.condition == '(D > E)' + assert str(case.iftrue.iftrue) == '<func (<char>), <int>, False>' + assert str(case.iftrue.iffalse) == '<func (<char>), <unsigned int>, False>' + assert str(case.iffalse) == '<func (<char>), <long>, False>' + +def test_conditional_reuse(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #endif + + #ifdef ABC + foo_t foo(char); + #endif + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert str(case.iftrue) == '<func (<char>), <int>, False>' + assert case.iffalse is None + +def test_conditional_reuse_nesting(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + # if D > E + typedef int foo_t; + # else + typedef unsigned int foo_t; + # endif + #endif + + #ifdef ABC + foo_t foo(char); + #endif + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == 'defined(ABC)' + assert case.iftrue.condition == '(D > E)' + assert str(case.iftrue.iftrue) == '<func (<char>), <int>, False>' + assert str(case.iftrue.iffalse) == '<func (<char>), <unsigned int>, False>' + assert case.iffalse is None + +def test_conditional_different_condition(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + typedef int foo_t; + #else + typedef long foo_t; + #endif + + #if D > E + foo_t foo(char); + #endif + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == '(D > E)' + assert case.iftrue.condition == 'defined(ABC)' + assert str(case.iftrue.iftrue) == '<func (<char>), <int>, False>' + assert str(case.iftrue.iffalse) == '<func (<char>), <unsigned int>, False>' + assert case.iffalse is None + +def test_conditional_reuse_reversed_nesting(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #ifdef ABC + # if D > E + typedef int foo_t; + # else + typedef unsigned int foo_t; + # endif + #else + typedef long foo_t; + #endif + + #if D > E + foo_t foo(char); + #endif + """) + case = ffi._parser._declarations['function foo'] + assert isinstance(case, ConditionalCase) + assert case.condition == '(D > E)' + assert case.iftrue.condition == 'defined(ABC)' + assert str(case.iftrue.iftrue) == '<func (<char>), <int>, False>' + assert str(case.iftrue.iffalse) == '<func (<char>), <long>, False>' + assert case.iffalse is None + def test_define_not_supported_for_now(): ffi = FFI(backend=FakeBackend()) e = py.test.raises(CDefError, ffi.cdef, '#define FOO "blah"') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit