Skip to content

Commit

Permalink
Add tests for compile-time failures
Browse files Browse the repository at this point in the history
Add an assertCompileFails() unittest method to
check that a given C++ code snippet fails to
compile due to a static_assert, and use it to
test compile time checks for std::get(IMP::Array)
and VectorD. Closes #1088.
  • Loading branch information
benmwebb committed Feb 2, 2024
1 parent 5972a94 commit e4dc6bb
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
18 changes: 18 additions & 0 deletions modules/algebra/test/expensive_test_vectord_mismatch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import IMP.test


class Tests(IMP.test.TestCase):

def test_vectord_mismatch(self):
"""Test combination of VectorD of different dimensions"""
# Should be a compile-time error to combine VectorD of different sizes
self.assertCompileFails(
includes=['IMP/algebra/VectorD.h'],
body="""
IMP::algebra::Vector3D v1(1,2,3);
IMP::algebra::Vector4D v3(7,8,9,10);
v1 -= v3;""")


if __name__ == '__main__':
IMP.test.main()
17 changes: 17 additions & 0 deletions modules/kernel/test/expensive_test_get_array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import IMP.test


class Tests(IMP.test.TestCase):

def test_get_array(self):
"""Test std::get<IMP::Array>"""
# Should be a compile-time error to access an out of range element
self.assertCompileFails(
includes=['IMP/base_types.h'],
body="""
IMP::ParticleIndexPair pp(IMP::ParticleIndex(1), IMP::ParticleIndex(3));
IMP::ParticleIndex p = std::get<2>(pp);""")


if __name__ == '__main__':
IMP.test.main()
36 changes: 36 additions & 0 deletions modules/test/pyext/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,42 @@ def assertSequenceAlmostEqual(self, first, second, places=None, msg=None,
msg = self._formatMessage(msg, standardMsg)
raise self.failureException(msg)

def _read_cmake_cache(self, cmake_cache):
"""Parse CMakeCache and extract info on the C++ compiler"""
cxx = flags = None
with open(cmake_cache) as fh:
for line in fh:
if line.startswith('CMAKE_CXX_COMPILER:'):
cxx = line.split('=', 1)[1].rstrip('\r\n')
elif line.startswith('CMAKE_CXX_FLAGS:'):
flags = line.split('=', 1)[1].rstrip('\r\n')
return cxx, flags

def assertCompileFails(self, includes, body):
"""Test that the given C++ code fails to compile with a static
assertion."""
libdir = os.path.dirname(IMP.__file__)
cmake_cache = os.path.join(libdir, '..', '..', 'CMakeCache.txt')
include = os.path.join(libdir, '..', '..', 'include')
if not os.path.exists(cmake_cache):
self.skipTest("cannot find CMakeCache.txt")
cxx, flags = self._read_cmake_cache(cmake_cache)
with temporary_directory() as tmpdir:
fname = os.path.join(tmpdir, 'test.cpp')
with open(fname, 'w') as fh:
for inc in includes:
fh.write("#include <%s>\n" % inc)
fh.write("\nint main() {\n" + body + "\n return 0;\n}\n")
cmdline = "%s %s -I%s %s" % (cxx, flags, include, fname)
print(cmdline)
p = subprocess.Popen(cmdline, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
out, err = p.communicate()
self.assertIn('error: static assertion failed', err)


def create_point_particle(self, model, x, y, z):
"""Make a particle with optimizable x, y and z attributes, and
add it to the model."""
Expand Down

0 comments on commit e4dc6bb

Please sign in to comment.