1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
"""
Unit test for Pybind wrap program
Author: Matthew Sklar, Varun Agrawal
Date: February 2019
"""
# pylint: disable=import-error, wrong-import-position, too-many-branches
import filecmp
import os
import os.path as osp
import sys
import unittest
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
sys.path.append(
osp.normpath(osp.abspath(osp.join(__file__, '../../../build/wrap'))))
from gtwrap.pybind_wrapper import PybindWrapper
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
class TestWrap(unittest.TestCase):
"""Tests for Python wrapper based on Pybind11."""
TEST_DIR = osp.dirname(osp.realpath(__file__))
INTERFACE_DIR = osp.join(TEST_DIR, 'fixtures')
PYTHON_TEST_DIR = osp.join(TEST_DIR, 'expected', 'python')
PYTHON_ACTUAL_DIR = osp.join(TEST_DIR, "actual", "python")
# Create the `actual/python` directory
os.makedirs(PYTHON_ACTUAL_DIR, exist_ok=True)
def wrap_content(self, sources, module_name, output_dir):
"""
Common function to wrap content in `sources`.
"""
with open(osp.join(self.TEST_DIR,
"pybind_wrapper.tpl")) as template_file:
module_template = template_file.read()
# Create Pybind wrapper instance
wrapper = PybindWrapper(module_name=module_name,
use_boost=False,
top_module_namespaces=[''],
ignore_classes=[''],
module_template=module_template)
output = osp.join(self.TEST_DIR, output_dir, module_name + ".cpp")
if not osp.exists(osp.join(self.TEST_DIR, output_dir)):
os.mkdir(osp.join(self.TEST_DIR, output_dir))
wrapper.wrap(sources, output)
return output
def compare_and_diff(self, file, actual):
"""
Compute the comparison between the expected and actual file,
and assert if diff is zero.
"""
expected = osp.join(self.PYTHON_TEST_DIR, file)
success = filecmp.cmp(actual, expected)
if not success:
os.system("diff {} {}".format(actual, expected))
self.assertTrue(success, "Mismatch for file {0}".format(file))
def test_geometry(self):
"""
Check generation of python geometry wrapper.
python3 ../pybind_wrapper.py --src geometry.h --module_name
geometry_py --out output/geometry_py.cc
"""
source = osp.join(self.INTERFACE_DIR, 'geometry.i')
output = self.wrap_content([source], 'geometry_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('geometry_pybind.cpp', output)
def test_functions(self):
"""Test interface file with function info."""
source = osp.join(self.INTERFACE_DIR, 'functions.i')
output = self.wrap_content([source], 'functions_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('functions_pybind.cpp', output)
def test_class(self):
"""Test interface file with only class info."""
source = osp.join(self.INTERFACE_DIR, 'class.i')
output = self.wrap_content([source], 'class_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('class_pybind.cpp', output)
def test_templates(self):
"""Test interface file with templated class."""
source = osp.join(self.INTERFACE_DIR, 'templates.i')
output = self.wrap_content([source], 'templates_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('templates_pybind.cpp', output)
def test_inheritance(self):
"""Test interface file with class inheritance definitions."""
source = osp.join(self.INTERFACE_DIR, 'inheritance.i')
output = self.wrap_content([source], 'inheritance_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('inheritance_pybind.cpp', output)
def test_namespaces(self):
"""
Check generation of python wrapper for full namespace definition.
python3 ../pybind_wrapper.py --src namespaces.i --module_name
namespaces_py --out output/namespaces_py.cpp
"""
source = osp.join(self.INTERFACE_DIR, 'namespaces.i')
output = self.wrap_content([source], 'namespaces_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('namespaces_pybind.cpp', output)
def test_operator_overload(self):
"""
Tests for operator overloading.
"""
source = osp.join(self.INTERFACE_DIR, 'operator.i')
output = self.wrap_content([source], 'operator_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('operator_pybind.cpp', output)
def test_special_cases(self):
"""
Tests for some unique, non-trivial features.
"""
source = osp.join(self.INTERFACE_DIR, 'special_cases.i')
output = self.wrap_content([source], 'special_cases_py',
self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('special_cases_pybind.cpp', output)
def test_enum(self):
"""
Test if enum generation is correct.
"""
source = osp.join(self.INTERFACE_DIR, 'enum.i')
output = self.wrap_content([source], 'enum_py', self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('enum_pybind.cpp', output)
if __name__ == '__main__':
unittest.main()
|