165 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
"""
 | 
						|
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,
 | 
						|
                     use_boost_serialization=False):
 | 
						|
        """
 | 
						|
        Common function to wrap content in `sources`.
 | 
						|
        """
 | 
						|
        with open(osp.join(self.TEST_DIR, "pybind_wrapper.tpl"),
 | 
						|
                  encoding="UTF-8") as template_file:
 | 
						|
            module_template = template_file.read()
 | 
						|
 | 
						|
        # Create Pybind wrapper instance
 | 
						|
        wrapper = PybindWrapper(
 | 
						|
            module_name=module_name,
 | 
						|
            top_module_namespaces=[''],
 | 
						|
            ignore_classes=[''],
 | 
						|
            module_template=module_template,
 | 
						|
            use_boost_serialization=use_boost_serialization)
 | 
						|
 | 
						|
        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(f"diff {actual} {expected}")
 | 
						|
        self.assertTrue(success, f"Mismatch for file {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,
 | 
						|
                                   use_boost_serialization=True)
 | 
						|
 | 
						|
        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()
 |