Skip to content

Commit

Permalink
Add additional tests
Browse files Browse the repository at this point in the history
Added an easy to maintain file based test suite. Just put a
`*.h` file into the `test/data/` directory for the input and
a corresponding `*.pxd` with the same name with the expected
output.

Currently not all tests are passing.
  • Loading branch information
vmx committed Mar 18, 2013
1 parent 8c767c7 commit 20cbefb
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.rst
Expand Up @@ -26,6 +26,12 @@ Getting started

less tests/result_clang/_test.pxd

* Additional testing (this command needs Python 2.7):

::

python -m unittest discover -s test

.. _Cython: http://www.cython.org
.. _libclang: http://clang.llvm.org/doxygen/group__CINDEX.html

Expand Down
17 changes: 17 additions & 0 deletions test/data/function.h
@@ -0,0 +1,17 @@
typedef struct _Bar {
double b;
} Bar;

typedef enum {
ONE,
TWO,
THREE,
FOUR,
FIVE,
} Baz;

// function which returns pointer to int
int *foo_bar(double t, Bar *barptr);

// function which returns a pointer to an array of 10 pointers to doubles
double *(*crazy_fn(int*, char*, Baz))[10];
15 changes: 15 additions & 0 deletions test/data/function.pxd
@@ -0,0 +1,15 @@
cdef extern from "function.h":
cdef struct _Bar:
double b
ctypedef _Bar Bar

ctypedef enum Baz:
ONE
TWO
THREE
FOUR
FIVE

int *foo_bar(double t, Bar *barptr)

double *((*crazy_fn(int *, char *, Baz))[10])
15 changes: 15 additions & 0 deletions test/data/functionpointer.h
@@ -0,0 +1,15 @@
// function that that takes int and returns pointer to function that takes
// two floats and returns float
float (*returns_func_ptr(int foo))(float, float);

// function which takes pointer to char and returns pointer to function which
// takes int and double and returns pointer to function that takes int and long
// and returns pointer to function that takes pointer to char and returns
// pointer to double.
double *(*(*(*returns_func_ptr_nested(char*))(int, double))(int, long))(char*);

// function pointer variable declaration
double (*func_ptr_var)(void);

// function pointer variable which returns function pointer which returns int
int (*(*func_ptr_func_ptr_var)(void))(void);
9 changes: 9 additions & 0 deletions test/data/functionpointer.pxd
@@ -0,0 +1,9 @@
cdef extern from "functionpointer.h":
float (*returns_func_ptr(int foo))(float, float)

double *(*(*(*returns_func_ptr_nested(char *))(int, double))(int, long))(char *)


double (*func_ptr_var)()

int (*(*func_ptr_func_ptr_var)())()
5 changes: 5 additions & 0 deletions test/data/functionpointer_in_struct.h
@@ -0,0 +1,5 @@
// struct with function pointer field which takes int and returns pointer
// to function which takes float pointer and returns pointer to char
struct CrazyField {
char *(*(*crazy_ptr)(int))(float*);
};
3 changes: 3 additions & 0 deletions test/data/functionpointer_in_struct.pxd
@@ -0,0 +1,3 @@
cdef extern from "functionpointer_in_struct.h":
cdef struct CrazyField:
char *(*(*crazy_ptr)(int))(float *)
8 changes: 8 additions & 0 deletions test/data/struct_with_typedef_field.h
@@ -0,0 +1,8 @@
// typdef of simple fundamental type
typedef long long LLong;

// struct containing typedef'd field
struct Foo {
int a;
LLong b;
};
6 changes: 6 additions & 0 deletions test/data/struct_with_typedef_field.pxd
@@ -0,0 +1,6 @@
cdef extern from "struct_with_typedef_field.h":
ctypedef long long LLong

cdef struct Foo:
int a
LLong b
1 change: 1 addition & 0 deletions test/data/typedef_simple.h
@@ -0,0 +1 @@
typedef long long LLong;
2 changes: 2 additions & 0 deletions test/data/typedef_simple.pxd
@@ -0,0 +1,2 @@
cdef extern from "typedef_simple.h":
ctypedef long long LLong
8 changes: 8 additions & 0 deletions test/data/union_with_struct.h
@@ -0,0 +1,8 @@
union AUnion {
int a;
double b;
long double c;
struct _sNested {
char* data;
} nested_data;
};
11 changes: 11 additions & 0 deletions test/data/union_with_struct.pxd
@@ -0,0 +1,11 @@
cdef extern from "union_with_struct.h":
cdef struct __AUnion__sNested:
char *data

ctypedef __AUnion__sNested __AUnion__sNested_t

cdef union AUnion:
int a
double b
long double c
__AUnion__sNested_t nested_data
63 changes: 63 additions & 0 deletions test/tests.py
@@ -0,0 +1,63 @@
import os
import unittest

from cwrap import frontends
from cwrap.backend import renderer
from cwrap.config import Config, File


def create_test(filename):
def do_test_file(self):
result = self.convert(filename + '.h')
expected = self.read_expected(filename + '.pxd')
print result
self.assertEqual(expected, result)
return do_test_file


class TestFiles(unittest.TestCase):

def setUp(self):
self.frontend = frontends.get_frontend('clang')

def convert(self, filename):
files = [File(filename)]
config = Config('clang', files=files)
asts = self.frontend.generate_asts(config)
print '\n\n\nvmx: asts:\n', asts, '\n\n\n\n\n'
ast_renderer = renderer.ASTRenderer()
for ast_container in asts:
mod_node = ast_container.module
code = ast_renderer.render(mod_node)
output = []
for line in code.splitlines():
if line.startswith('#') or not line.strip():
continue
output.append(line.strip())
return output

def read_expected(self, filename):
output = []
with file(filename) as f:
for line in f:
if line.startswith('#') or not line.strip():
continue
output.append(line.strip())
return output


if __name__ == '__main__':
unittest.main()


# Thanks for the hint: http://stackoverflow.com/questions/2798956/python-unittest-generate-multiple-tests-programmatically
curdir = os.path.dirname(__file__)
testfiles = os.listdir(os.path.join(curdir, 'data'))
testfiles.sort()
testfiles = [os.path.join(curdir, 'data', f) for f in testfiles]
testfiles = [os.path.splitext(f)[0] for f in testfiles if f.endswith('.h')]
print 'Files to test:', testfiles
for testfile in testfiles:
test_method = create_test(testfile)
test_method.__name__ = 'test_' + os.path.basename(testfile)
setattr(TestFiles, test_method.__name__, test_method)

0 comments on commit 20cbefb

Please sign in to comment.