abi_test_tools.hpp 4.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Copyright Andrey Semashev 2018.
  3. * Distributed under the Boost Software License, Version 1.0.
  4. * (See accompanying file LICENSE_1_0.txt or copy at
  5. * http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. /*!
  8. * \file abi_test_tools.hpp
  9. * \author Andrey Semashev
  10. * \date 09.03.2018
  11. *
  12. * \brief This file contains a set of ABI testing tools
  13. */
  14. #ifndef BOOST_WINAPI_TEST_RUN_ABI_TEST_TOOLS_HPP_INCLUDED_
  15. #define BOOST_WINAPI_TEST_RUN_ABI_TEST_TOOLS_HPP_INCLUDED_
  16. #include <boost/winapi/config.hpp>
  17. #include <boost/config.hpp>
  18. #include <boost/current_function.hpp>
  19. #include <boost/core/is_same.hpp>
  20. #include <boost/core/lightweight_test.hpp>
  21. #include <boost/core/lightweight_test_trait.hpp>
  22. #include <boost/preprocessor/seq/for_each.hpp>
  23. #include <boost/preprocessor/tuple/elem.hpp>
  24. #include <cstddef> // offsetof
  25. //! The macro produces Boost.WinAPI equivalent for a Windows SDK constant or type name
  26. #define BOOST_WINAPI_NAME(name)\
  27. boost::winapi::name
  28. //! The macro tests that the given constant has the same value in Boost.WinAPI and Windows SDK
  29. #define BOOST_WINAPI_TEST_CONSTANT(name)\
  30. BOOST_TEST_EQ(name, BOOST_WINAPI_NAME(name ## _))
  31. //! The macro tests that the given type is the same in Boost.WinAPI and Windows SDK
  32. #define BOOST_WINAPI_TEST_TYPE_SAME(name)\
  33. BOOST_TEST_TRAIT_TRUE((boost::core::is_same< name, BOOST_WINAPI_NAME(name ## _) >))
  34. //! The macro tests that the given type has the same size in Boost.WinAPI and Windows SDK
  35. #define BOOST_WINAPI_TEST_TYPE_SIZE(name)\
  36. BOOST_TEST_EQ(sizeof(name), sizeof(BOOST_WINAPI_NAME(name ## _)))
  37. #define BOOST_WINAPI_TEST_STRUCT_FIELD(r, names, field)\
  38. BOOST_TEST_EQ(sizeof(BOOST_PP_TUPLE_ELEM(2, 0, names)().field), sizeof(BOOST_PP_TUPLE_ELEM(2, 1, names)().field));\
  39. BOOST_TEST_EQ(offsetof(BOOST_PP_TUPLE_ELEM(2, 0, names), field), offsetof(BOOST_PP_TUPLE_ELEM(2, 1, names), field));
  40. //! The macro tests that the structure has the same size, and its fields have the same size and offsets in Boost.WinAPI and Windows SDK
  41. #define BOOST_WINAPI_TEST_STRUCT(name, fields)\
  42. BOOST_PP_SEQ_FOR_EACH(BOOST_WINAPI_TEST_STRUCT_FIELD, (name, BOOST_WINAPI_NAME(name ## _)), fields)\
  43. BOOST_TEST_EQ(sizeof(name), sizeof(BOOST_WINAPI_NAME(name ## _)))
  44. #if defined(BOOST_MSVC)
  45. #pragma warning(push, 3)
  46. // conditional expression is constant
  47. #pragma warning(disable: 4127)
  48. #endif
  49. template< typename Windows_SDK_Signature, typename BoostWinAPI_Signature >
  50. inline void test_equal_signatures(Windows_SDK_Signature*, BoostWinAPI_Signature*, const char* test_name, const char* file, int line)
  51. {
  52. if (!boost::core::is_same< Windows_SDK_Signature, BoostWinAPI_Signature >::value)
  53. boost::detail::test_failed_impl(test_name, file, line, BOOST_CURRENT_FUNCTION); // pass BOOST_CURRENT_FUNCTION here to include signature types in the error message
  54. }
  55. #if defined(BOOST_MSVC)
  56. #pragma warning(pop)
  57. #endif
  58. /*!
  59. * \brief The macro tests that the given function signature is the same in Boost.WinAPI and Windows SDK
  60. *
  61. * If the signatures don't match, the test may fail to compile instead of failing at runtime. Depending on the compiler,
  62. * the error message may say that either there are multiple different declarations of an extern "C" function, or that
  63. * \c test_equal_signatures cannot be instantiated because of an unresolved overloaded function. This is because we currently
  64. * have forward declarations of Windows functions in the global namespace, so technically the declaration from Boost.WinAPI
  65. * and from Windows SDK are either two declarations of the same function (if they match) or declarations of two overloaded
  66. * functions (which is an error because both of them are extern "C"). Anyway, the test will fail if there's an error and
  67. * will pass if everything's fine, which is what we want.
  68. *
  69. * \note Do not use this macro to compare function signatures where we use our own structures binary-compatible with Windows SDK.
  70. * Such functions are defined as inline wrappers in Boost.WinAPI headers and the wrappers will obviously not compare equal
  71. * to the functions in Windows SDK. Currently, there's no way to test those function declarations because Boost.WinAPI
  72. * declares Windows functions in the global namespace. They are implicitly tested by the compiler though, which should fail
  73. * to compile if the declarations don't match.
  74. */
  75. #if !defined(BOOST_NO_CXX11_DECLTYPE)
  76. #define BOOST_WINAPI_TEST_FUNCTION_SIGNATURE(name)\
  77. test_equal_signatures((decltype(&name))0, (decltype(&BOOST_WINAPI_NAME(name)))0, "BOOST_WINAPI_TEST_FUNCTION_SIGNATURE(" #name ")", __FILE__, __LINE__)
  78. #else
  79. #define BOOST_WINAPI_TEST_FUNCTION_SIGNATURE(name)\
  80. test_equal_signatures(&name, &BOOST_WINAPI_NAME(name), "BOOST_WINAPI_TEST_FUNCTION_SIGNATURE(" #name ")", __FILE__, __LINE__)
  81. #endif
  82. #endif // BOOST_WINAPI_TEST_RUN_ABI_TEST_TOOLS_HPP_INCLUDED_