gtsam/wrap/tests/test_matlab_wrapper.py

300 lines
9.0 KiB
Python

"""
Unit tests for Matlab wrap program
Author: Matthew Sklar, Varun Agrawal
Date: March 2019
"""
# pylint: disable=import-error, wrong-import-position
import filecmp
import os
import os.path as osp
import sys
import unittest
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from gtwrap.matlab_wrapper import MatlabWrapper
class TestWrap(unittest.TestCase):
"""
Test the Matlab wrapper
"""
def setUp(self) -> None:
super().setUp()
# Set up all the directories
self.TEST_DIR = osp.dirname(osp.realpath(__file__))
self.INTERFACE_DIR = osp.join(self.TEST_DIR, "fixtures")
self.MATLAB_TEST_DIR = osp.join(self.TEST_DIR, "expected", "matlab")
self.MATLAB_ACTUAL_DIR = osp.join(self.TEST_DIR, "actual", "matlab")
if not osp.exists(self.MATLAB_ACTUAL_DIR):
os.mkdir(self.MATLAB_ACTUAL_DIR)
# Generate the matlab.h file if it does not exist
template_file = osp.join(self.TEST_DIR, "..", "gtwrap",
"matlab_wrapper", "matlab_wrapper.tpl")
if not osp.exists(template_file):
with open(template_file, 'w', encoding="UTF-8") as tpl:
tpl.write("#include <gtwrap/matlab.h>\n#include <map>\n")
# Create the `actual/matlab` directory
os.makedirs(self.MATLAB_ACTUAL_DIR, exist_ok=True)
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.MATLAB_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 matlab geometry wrapper.
python3 wrap/matlab_wrapper.py --src wrap/tests/geometry.h
--module_name geometry --out wrap/tests/actual-matlab
"""
file = osp.join(self.INTERFACE_DIR, 'geometry.i')
# Create MATLAB wrapper instance
wrapper = MatlabWrapper(module_name='geometry',
top_module_namespace=['gtsam'],
ignore_classes=[''],
use_boost_serialization=True)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = ['+gtsam/Point2.m', '+gtsam/Point3.m', 'geometry_wrapper.cpp']
self.assertTrue(osp.isdir(osp.join(self.MATLAB_ACTUAL_DIR, '+gtsam')))
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_functions(self):
"""Test interface file with function info."""
file = osp.join(self.INTERFACE_DIR, 'functions.i')
wrapper = MatlabWrapper(
module_name='functions',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = [
'functions_wrapper.cpp',
'aGlobalFunction.m',
'load2D.m',
'MultiTemplatedFunctionDoubleSize_tDouble.m',
'MultiTemplatedFunctionStringSize_tDouble.m',
'overloadedGlobalFunction.m',
'TemplatedFunctionRot3.m',
'DefaultFuncInt.m',
'DefaultFuncObj.m',
'DefaultFuncString.m',
'DefaultFuncVector.m',
'DefaultFuncZero.m',
'setPose.m',
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_class(self):
"""Test interface file with only class info."""
file = osp.join(self.INTERFACE_DIR, 'class.i')
wrapper = MatlabWrapper(
module_name='class',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = [
'class_wrapper.cpp',
'FunDouble.m',
'FunRange.m',
'MultipleTemplatesIntDouble.m',
'MultipleTemplatesIntFloat.m',
'MyFactorPosePoint2.m',
'MyVector3.m',
'MyVector12.m',
'PrimitiveRefDouble.m',
'Test.m',
'ForwardKinematics.m',
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_enum(self):
"""Test interface file with only enum info."""
file = osp.join(self.INTERFACE_DIR, 'enum.i')
wrapper = MatlabWrapper(
module_name='enum',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = [
'enum_wrapper.cpp',
'Color.m',
'+Pet/Kind.m',
'+gtsam/VerbosityLM.m',
'+gtsam/+MCU/Avengers.m',
'+gtsam/+MCU/GotG.m',
'+gtsam/+OptimizerGaussNewtonParams/Verbosity.m',
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_templates(self):
"""Test interface file with template info."""
file = osp.join(self.INTERFACE_DIR, 'templates.i')
wrapper = MatlabWrapper(
module_name='template',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = [
'template_wrapper.cpp', 'ScopedTemplateResult.m',
'TemplatedConstructor.m'
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_inheritance(self):
"""Test interface file with class inheritance definitions."""
file = osp.join(self.INTERFACE_DIR, 'inheritance.i')
wrapper = MatlabWrapper(
module_name='inheritance',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = [
'inheritance_wrapper.cpp',
'MyBase.m',
'MyTemplateMatrix.m',
'MyTemplatePoint2.m',
'ForwardKinematicsFactor.m',
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_namespaces(self):
"""
Test interface file with full namespace definition.
"""
file = osp.join(self.INTERFACE_DIR, 'namespaces.i')
wrapper = MatlabWrapper(
module_name='namespaces',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = [
'namespaces_wrapper.cpp',
'+ns1/aGlobalFunction.m',
'+ns1/ClassA.m',
'+ns1/ClassB.m',
'+ns2/+ns3/ClassB.m',
'+ns2/aGlobalFunction.m',
'+ns2/ClassA.m',
'+ns2/ClassC.m',
'+ns2/overloadedGlobalFunction.m',
'ClassD.m',
'+gtsam/Values.m',
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_special_cases(self):
"""
Tests for some unique, non-trivial features.
"""
file = osp.join(self.INTERFACE_DIR, 'special_cases.i')
wrapper = MatlabWrapper(
module_name='special_cases',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
files = [
'special_cases_wrapper.cpp',
'+gtsam/GeneralSFMFactorCal3Bundler.m',
'+gtsam/NonlinearFactorGraph.m',
'+gtsam/PinholeCameraCal3Bundler.m',
'+gtsam/SfmTrack.m',
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
def test_multiple_files(self):
"""
Test for when multiple interface files are specified.
"""
file1 = osp.join(self.INTERFACE_DIR, 'part1.i')
file2 = osp.join(self.INTERFACE_DIR, 'part2.i')
wrapper = MatlabWrapper(
module_name='multiple_files',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file1, file2], path=self.MATLAB_ACTUAL_DIR)
files = [
'multiple_files_wrapper.cpp',
'+gtsam/Class1.m',
'+gtsam/Class2.m',
'+gtsam/ClassA.m',
]
for file in files:
actual = osp.join(self.MATLAB_ACTUAL_DIR, file)
self.compare_and_diff(file, actual)
if __name__ == '__main__':
unittest.main()