diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml new file mode 100644 index 000000000..7c4bf40cf --- /dev/null +++ b/.github/workflows/mac-build.yml @@ -0,0 +1,32 @@ +name: macOS build and tests +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + schedule: + - cron: '38 2 * * *' + +jobs: + mac-build: + name: macOS (${{ matrix.arch }}) + timeout-minutes: 30 + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - runner: macos-15 + arch: arm64 + - runner: macos-15-intel + arch: x86_64 + + steps: + - uses: actions/checkout@v6 + - name: configure + run: mkdir build && cd build && cmake .. -DBUILDING_TESTS=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} + - name: build + run: cmake --build build + - name: test + run: cd build && ctest --output-on-failure diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index 956479f02..1896dd953 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -5,6 +5,8 @@ on: push: branches: - master + schedule: + - cron: '38 2 * * *' jobs: win-build: diff --git a/3rdparty/endian/endian.h b/3rdparty/endian/endian.h deleted file mode 100644 index 9c5500b2f..000000000 --- a/3rdparty/endian/endian.h +++ /dev/null @@ -1,103 +0,0 @@ -// -// endian.h -// -// https://gist.github.com/panzi/6856583 -// -// I, Mathias Panzenböck, place this file hereby into the public domain. Use -// it at your own risk for whatever you like. In case there are -// jurisdictions that don't support putting things in the public domain you -// can also consider it to be "dual licensed" under the BSD, MIT and Apache -// licenses, if you want to. This code is trivial anyway. Consider it an -// example on how to get the endian conversion functions on different -// platforms. - -#ifndef PORTABLE_ENDIAN_H__ -#define PORTABLE_ENDIAN_H__ - -// Byte order -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__CYGWIN__) -# include -#elif defined(__APPLE__) -# include - -# define htobe16(x) OSSwapHostToBigInt16(x) -# define htole16(x) OSSwapHostToLittleInt16(x) -# define be16toh(x) OSSwapBigToHostInt16(x) -# define le16toh(x) OSSwapLittleToHostInt16(x) - -# define htobe32(x) OSSwapHostToBigInt32(x) -# define htole32(x) OSSwapHostToLittleInt32(x) -# define be32toh(x) OSSwapBigToHostInt32(x) -# define le32toh(x) OSSwapLittleToHostInt32(x) - -# define htobe64(x) OSSwapHostToBigInt64(x) -# define htole64(x) OSSwapHostToLittleInt64(x) -# define be64toh(x) OSSwapBigToHostInt64(x) -# define le64toh(x) OSSwapLittleToHostInt64(x) - -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN -#elif defined(__OpenBSD__) -# include -#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) -# include - -# define be16toh(x) betoh16(x) -# define le16toh(x) letoh16(x) - -# define be32toh(x) betoh32(x) -# define le32toh(x) letoh32(x) - -# define be64toh(x) betoh64(x) -# define le64toh(x) letoh64(x) -#elif defined(_WIN32) -# include -# if BYTE_ORDER == LITTLE_ENDIAN -# if defined(_MSC_VER) -# define htobe16(x) _byteswap_ushort(x) -# define htole16(x) (x) -# define be16toh(x) _byteswap_ushort(x) -# define le16toh(x) (x) - -# define htobe32(x) _byteswap_ulong(x) -# define htole32(x) (x) -# define be32toh(x) _byteswap_ulong(x) -# define le32toh(x) (x) - -# define htobe64(x) _byteswap_uint64(x) -# define htole64(x) (x) -# define be64toh(x) _byteswap_uint64(x) -# define le64toh(x) (x) -# elif defined(__GNUC__) || defined(__clang__) -# define htobe16(x) __builtin_bswap16(x) -# define htole16(x) (x) -# define be16toh(x) __builtin_bswap16(x) -# define le16toh(x) (x) - -# define htobe32(x) __builtin_bswap32(x) -# define htole32(x) (x) -# define be32toh(x) __builtin_bswap32(x) -# define le32toh(x) (x) - -# define htobe64(x) __builtin_bswap64(x) -# define htole64(x) (x) -# define be64toh(x) __builtin_bswap64(x) -# define le64toh(x) (x) -# else -# error Compiler is not supported -# endif -# else -# error Byte order is not supported -# endif - -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN -#else -# error Platform is not supported -#endif - -#endif // PORTABLE_ENDIAN_H__ diff --git a/CMakeLists.txt b/CMakeLists.txt index 144908276..3dd148d99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,17 +66,7 @@ target_compile_features(urcl PUBLIC cxx_std_17) if(MSVC) target_link_libraries(urcl ws2_32) - target_include_directories(urcl PUBLIC - $ - $ - ) else() - if(APPLE) - target_include_directories(urcl PUBLIC - $ - $ - ) - endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic") target_compile_options(urcl PRIVATE -Wall -Wextra -Wno-unused-parameter) @@ -121,11 +111,6 @@ install(TARGETS urcl EXPORT urcl_targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) install(DIRECTORY include/ DESTINATION include) -if(MSVC OR APPLE) - install(DIRECTORY 3rdparty/endian/ DESTINATION include/${PROJECT_NAME}/3rdparty - FILES_MATCHING PATTERN "*.h" - ) -endif() install(EXPORT urcl_targets DESTINATION lib/cmake/ur_client_library diff --git a/include/ur_client_library/comm/bin_parser.h b/include/ur_client_library/comm/bin_parser.h index e13aba6b9..32540ca1b 100644 --- a/include/ur_client_library/comm/bin_parser.h +++ b/include/ur_client_library/comm/bin_parser.h @@ -21,7 +21,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/include/ur_client_library/comm/package_serializer.h b/include/ur_client_library/comm/package_serializer.h index 01fa85751..69f3431b4 100644 --- a/include/ur_client_library/comm/package_serializer.h +++ b/include/ur_client_library/comm/package_serializer.h @@ -29,7 +29,7 @@ #ifndef UR_CLIENT_LIBRARY_PACKAGE_SERIALIZER_H_INCLUDED #define UR_CLIENT_LIBRARY_PACKAGE_SERIALIZER_H_INCLUDED -#include +#include #include #include #include diff --git a/include/ur_client_library/control/reverse_interface.h b/include/ur_client_library/control/reverse_interface.h index 37e1dee9a..994521ca6 100644 --- a/include/ur_client_library/control/reverse_interface.h +++ b/include/ur_client_library/control/reverse_interface.h @@ -36,7 +36,6 @@ #include "ur_client_library/ur/robot_receive_timeout.h" #include "ur_client_library/ur/version_information.h" #include -#include #include #include diff --git a/include/ur_client_library/portable_endian.h b/include/ur_client_library/portable_endian.h new file mode 100644 index 000000000..679a3e0a3 --- /dev/null +++ b/include/ur_client_library/portable_endian.h @@ -0,0 +1,203 @@ +// +// portable_endian.h +// +// https://gist.github.com/panzi/6856583 +// +// I, Mathias Panzenböck, place this file hereby into the public domain. Use +// it at your own risk for whatever you like. In case there are +// jurisdictions that don't support putting things in the public domain you +// can also consider it to be "dual licensed" under the BSD, MIT and Apache +// licenses, if you want to. This code is trivial anyway. Consider it an +// example on how to get the endian conversion functions on different +// platforms. + +#ifndef UR_CLIENT_LIBRARY_PORTABLE_ENDIAN_H_INCLUDED +#define UR_CLIENT_LIBRARY_PORTABLE_ENDIAN_H_INCLUDED + +// Byte order +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__CYGWIN__) +# include +#elif defined(__APPLE__) +# include + +# ifndef htobe16 +# define htobe16(x) OSSwapHostToBigInt16(x) +# endif +# ifndef htole16 +# define htole16(x) OSSwapHostToLittleInt16(x) +# endif +# ifndef be16toh +# define be16toh(x) OSSwapBigToHostInt16(x) +# endif +# ifndef le16toh +# define le16toh(x) OSSwapLittleToHostInt16(x) +# endif + +# ifndef htobe32 +# define htobe32(x) OSSwapHostToBigInt32(x) +# endif +# ifndef htole32 +# define htole32(x) OSSwapHostToLittleInt32(x) +# endif +# ifndef be32toh +# define be32toh(x) OSSwapBigToHostInt32(x) +# endif +# ifndef le32toh +# define le32toh(x) OSSwapLittleToHostInt32(x) +# endif + +# ifndef htobe64 +# define htobe64(x) OSSwapHostToBigInt64(x) +# endif +# ifndef htole64 +# define htole64(x) OSSwapHostToLittleInt64(x) +# endif +# ifndef be64toh +# define be64toh(x) OSSwapBigToHostInt64(x) +# endif +# ifndef le64toh +# define le64toh(x) OSSwapLittleToHostInt64(x) +# endif + +# ifndef __BYTE_ORDER +# define __BYTE_ORDER BYTE_ORDER +# endif +# ifndef __BIG_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +# endif +# ifndef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# endif +# ifndef __PDP_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN +# endif +#elif defined(__OpenBSD__) +# include +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) +# include + +# ifndef be16toh +# define be16toh(x) betoh16(x) +# endif +# ifndef le16toh +# define le16toh(x) letoh16(x) +# endif + +# ifndef be32toh +# define be32toh(x) betoh32(x) +# endif +# ifndef le32toh +# define le32toh(x) letoh32(x) +# endif + +# ifndef be64toh +# define be64toh(x) betoh64(x) +# endif +# ifndef le64toh +# define le64toh(x) letoh64(x) +# endif +#elif defined(_WIN32) +# include +# if BYTE_ORDER == LITTLE_ENDIAN +# if defined(_MSC_VER) +# ifndef htobe16 +# define htobe16(x) _byteswap_ushort(x) +# endif +# ifndef htole16 +# define htole16(x) (x) +# endif +# ifndef be16toh +# define be16toh(x) _byteswap_ushort(x) +# endif +# ifndef le16toh +# define le16toh(x) (x) +# endif + +# ifndef htobe32 +# define htobe32(x) _byteswap_ulong(x) +# endif +# ifndef htole32 +# define htole32(x) (x) +# endif +# ifndef be32toh +# define be32toh(x) _byteswap_ulong(x) +# endif +# ifndef le32toh +# define le32toh(x) (x) +# endif + +# ifndef htobe64 +# define htobe64(x) _byteswap_uint64(x) +# endif +# ifndef htole64 +# define htole64(x) (x) +# endif +# ifndef be64toh +# define be64toh(x) _byteswap_uint64(x) +# endif +# ifndef le64toh +# define le64toh(x) (x) +# endif +# elif defined(__GNUC__) || defined(__clang__) +# ifndef htobe16 +# define htobe16(x) __builtin_bswap16(x) +# endif +# ifndef htole16 +# define htole16(x) (x) +# endif +# ifndef be16toh +# define be16toh(x) __builtin_bswap16(x) +# endif +# ifndef le16toh +# define le16toh(x) (x) +# endif + +# ifndef htobe32 +# define htobe32(x) __builtin_bswap32(x) +# endif +# ifndef htole32 +# define htole32(x) (x) +# endif +# ifndef be32toh +# define be32toh(x) __builtin_bswap32(x) +# endif +# ifndef le32toh +# define le32toh(x) (x) +# endif + +# ifndef htobe64 +# define htobe64(x) __builtin_bswap64(x) +# endif +# ifndef htole64 +# define htole64(x) (x) +# endif +# ifndef be64toh +# define be64toh(x) __builtin_bswap64(x) +# endif +# ifndef le64toh +# define le64toh(x) (x) +# endif +# else +# error Compiler is not supported +# endif +# else +# error Byte order is not supported +# endif + +# ifndef __BYTE_ORDER +# define __BYTE_ORDER BYTE_ORDER +# endif +# ifndef __BIG_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +# endif +# ifndef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# endif +# ifndef __PDP_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN +# endif +#else +# error Platform is not supported +#endif + +#endif // UR_CLIENT_LIBRARY_PORTABLE_ENDIAN_H_INCLUDED diff --git a/include/ur_client_library/primary/package_header.h b/include/ur_client_library/primary/package_header.h index cd64bdaf0..e8e0b990b 100644 --- a/include/ur_client_library/primary/package_header.h +++ b/include/ur_client_library/primary/package_header.h @@ -32,7 +32,7 @@ #include #include -#include +#include #include "ur_client_library/types.h" namespace urcl diff --git a/include/ur_client_library/rtde/package_header.h b/include/ur_client_library/rtde/package_header.h index f910a0843..cc564c0c5 100644 --- a/include/ur_client_library/rtde/package_header.h +++ b/include/ur_client_library/rtde/package_header.h @@ -31,7 +31,7 @@ #define UR_CLIENT_LIBRARY_RTDE__HEADER_H_INCLUDED #include -#include +#include #include "ur_client_library/types.h" #include "ur_client_library/comm/package_serializer.h" diff --git a/src/comm/tcp_socket.cpp b/src/comm/tcp_socket.cpp index de1891013..6af840e0d 100644 --- a/src/comm/tcp_socket.cpp +++ b/src/comm/tcp_socket.cpp @@ -20,7 +20,6 @@ * limitations under the License. */ -#include #include #include #include diff --git a/src/control/reverse_interface.cpp b/src/control/reverse_interface.cpp index 356cd09a4..6c1a25e72 100644 --- a/src/control/reverse_interface.cpp +++ b/src/control/reverse_interface.cpp @@ -27,6 +27,7 @@ //---------------------------------------------------------------------- #include +#include #include namespace urcl diff --git a/src/control/script_command_interface.cpp b/src/control/script_command_interface.cpp index 956b032f6..a0af94049 100644 --- a/src/control/script_command_interface.cpp +++ b/src/control/script_command_interface.cpp @@ -27,6 +27,7 @@ //---------------------------------------------------------------------- #include +#include #include namespace urcl diff --git a/src/control/trajectory_point_interface.cpp b/src/control/trajectory_point_interface.cpp index b3b6d0b15..ccc671886 100644 --- a/src/control/trajectory_point_interface.cpp +++ b/src/control/trajectory_point_interface.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include diff --git a/tests/test_bin_parser.cpp b/tests/test_bin_parser.cpp index c4f9818cf..290d0d3cf 100644 --- a/tests/test_bin_parser.cpp +++ b/tests/test_bin_parser.cpp @@ -136,6 +136,42 @@ TEST(bin_parser, parse_array) } } +TEST(bin_parser, parse_vector6int32_signed) +{ + // Big-endian 6 x int32_t: -1, -256, 255, 0x7fffffff, -0x80000000, 42 + uint8_t buffer[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x7f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a }; + comm::BinParser bp(buffer, sizeof(buffer)); + + vector6int32_t expected = { -1, -256, 255, 2147483647, static_cast(0x80000000u), 42 }; + vector6int32_t parsed; + bp.parse(parsed); + + for (size_t i = 0; i < expected.size(); ++i) + { + EXPECT_EQ(expected[i], parsed[i]) << "at index " << i; + } + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, parse_vector6uint32_unsigned) +{ + // Big-endian 6 x uint32_t: 0, 1, 255, 0xffffffff, 0x80000000, 0x7fffffff + uint8_t buffer[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff }; + comm::BinParser bp(buffer, sizeof(buffer)); + + vector6uint32_t expected = { 0u, 1u, 255u, 4294967295u, 2147483648u, 2147483647u }; + vector6uint32_t parsed; + bp.parse(parsed); + + for (size_t i = 0; i < expected.size(); ++i) + { + EXPECT_EQ(expected[i], parsed[i]) << "at index " << i; + } + EXPECT_TRUE(bp.empty()); +} + TEST(bin_parser, parse_data_types) { // Parse float value @@ -148,15 +184,26 @@ TEST(bin_parser, parse_data_types) EXPECT_EQ(expected_float, parsed_float); - // Parse double value - uint8_t buffer_double[] = { 0x41, 0xb2, 0xb8, 0x52, 0xcc, 0x55, 0x00, 0x00 }; + // Parse float value from buffer (float overload reads only 4 bytes; remaining bytes stay in buffer) + uint8_t buffer_float_4bytes[] = { 0x41, 0xb2, 0xb8, 0x52, 0xcc, 0x55, 0x00, 0x00 }; + comm::BinParser bp_float_4bytes(buffer_float_4bytes, sizeof(buffer_float_4bytes)); + + float expected_float_4bytes = 22.34f; + float parsed_float_4bytes; + bp_float_4bytes.parse(parsed_float_4bytes); + + EXPECT_EQ(expected_float_4bytes, parsed_float_4bytes); + EXPECT_FALSE(bp_float_4bytes.empty()); // 4 bytes remain unparsed + + // Parse double value (2.0 has exact IEEE 754 big-endian representation) + uint8_t buffer_double[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; comm::BinParser bp_double(buffer_double, sizeof(buffer_double)); - float expected_double = 22.34; - float parsed_double; + constexpr double kExpectedDouble = 2.0; + double parsed_double; bp_double.parse(parsed_double); - EXPECT_EQ(expected_double, parsed_double); + EXPECT_DOUBLE_EQ(kExpectedDouble, parsed_double); // Parse boolean uint8_t buffer_bool[] = { 0x01 }; @@ -295,6 +342,133 @@ TEST(bin_parser, bin_parser_parent) EXPECT_EQ(expected_message, parsed_message); } +// Tests for integer decoding (big-endian to host) - covers logic in bin_parser.cpp +TEST(bin_parser, decode_uint8) +{ + uint8_t buffer[] = { 0xab }; + comm::BinParser bp(buffer, sizeof(buffer)); + uint8_t val; + bp.parse(val); + EXPECT_EQ(val, 0xab); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, decode_uint16) +{ + // Big-endian 0x1234 + uint8_t buffer[] = { 0x12, 0x34 }; + comm::BinParser bp(buffer, sizeof(buffer)); + uint16_t val; + bp.parse(val); + EXPECT_EQ(val, 0x1234u); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, decode_uint32) +{ + // Big-endian 0x12345678 + uint8_t buffer[] = { 0x12, 0x34, 0x56, 0x78 }; + comm::BinParser bp(buffer, sizeof(buffer)); + uint32_t val; + bp.parse(val); + EXPECT_EQ(val, 0x12345678u); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, decode_uint64) +{ + // Big-endian 0x123456789abcdef0 + uint8_t buffer[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 }; + comm::BinParser bp(buffer, sizeof(buffer)); + uint64_t val; + bp.parse(val); + EXPECT_EQ(val, 0x123456789abcdef0ULL); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, decode_int16) +{ + // Big-endian -1 (0xffff) + uint8_t buffer[] = { 0xff, 0xff }; + comm::BinParser bp(buffer, sizeof(buffer)); + int16_t val; + bp.parse(val); + EXPECT_EQ(val, -1); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, decode_int64) +{ + // Big-endian -1 + uint8_t buffer[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + comm::BinParser bp(buffer, sizeof(buffer)); + int64_t val; + bp.parse(val); + EXPECT_EQ(val, -1); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, peek_does_not_advance) +{ + uint8_t buffer[] = { 0x12, 0x34, 0x56, 0x78 }; + comm::BinParser bp(buffer, sizeof(buffer)); + + uint32_t a = bp.peek(); + uint32_t b = bp.peek(); + EXPECT_EQ(a, 0x12345678u); + EXPECT_EQ(b, 0x12345678u); + + uint32_t c; + bp.parse(c); + EXPECT_EQ(c, 0x12345678u); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, parse_string_with_length_prefix) +{ + // Length 5, then "hello" + uint8_t buffer[] = { 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f }; + comm::BinParser bp(buffer, sizeof(buffer)); + + std::string s; + bp.parse(s); + EXPECT_EQ(s, "hello"); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, parse_string_with_length_prefix_empty) +{ + uint8_t buffer[] = { 0x00 }; + comm::BinParser bp(buffer, sizeof(buffer)); + + std::string s; + bp.parse(s); + EXPECT_TRUE(s.empty()); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, parse_bool_false) +{ + uint8_t buffer[] = { 0x00 }; + comm::BinParser bp(buffer, sizeof(buffer)); + bool val; + bp.parse(val); + EXPECT_FALSE(val); + EXPECT_TRUE(bp.empty()); +} + +TEST(bin_parser, peek_throws_when_past_end) +{ + uint8_t buffer[] = { 0x12, 0x34 }; + comm::BinParser bp(buffer, sizeof(buffer)); + + EXPECT_THROW(bp.peek(), UrException); + uint16_t val; + bp.parse(val); + EXPECT_EQ(val, 0x1234u); + EXPECT_THROW(bp.peek(), UrException); +} + int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); diff --git a/tests/test_package_serializer.cpp b/tests/test_package_serializer.cpp index 779712790..e9760b9c2 100644 --- a/tests/test_package_serializer.cpp +++ b/tests/test_package_serializer.cpp @@ -183,7 +183,7 @@ TEST(package_serializer, serialize_vector6int32) int32_t tmp; std::memcpy(&tmp, &buffer[i * sizeof(int32_t)], sizeof(int32_t)); int32_t decoded = be32toh(tmp); - EXPECT_DOUBLE_EQ(decoded, target[i]); + EXPECT_EQ(decoded, target[i]); } } @@ -201,7 +201,7 @@ TEST(package_serializer, serialize_vector6uint32) uint32_t tmp; std::memcpy(&tmp, &buffer[i * sizeof(uint32_t)], sizeof(uint32_t)); uint32_t decoded = be32toh(tmp); - EXPECT_DOUBLE_EQ(decoded, target[i]); + EXPECT_EQ(decoded, target[i]); } } @@ -233,13 +233,123 @@ TEST(package_serializer, serialize_bool) bool decoded_bool; std::memcpy(&decoded_bool, &buffer, sizeof(uint8_t)); - EXPECT_DOUBLE_EQ(decoded_bool, target); + EXPECT_EQ(decoded_bool, target); - target = false; + target = true; actual_size = comm::PackageSerializer::serialize(buffer, target); EXPECT_EQ(expected_size, actual_size); std::memcpy(&decoded_bool, &buffer, sizeof(uint8_t)); - EXPECT_DOUBLE_EQ(decoded_bool, target); + EXPECT_EQ(decoded_bool, target); +} + +// Tests for encode() logic in package_serializer.cpp (host to big-endian) +TEST(package_serializer, serialize_uint8) +{ + constexpr uint8_t kVal = 0xab; + uint8_t buffer[1]; + size_t size = comm::PackageSerializer::serialize(buffer, kVal); + EXPECT_EQ(size, 1u); + EXPECT_EQ(buffer[0], kVal); +} + +TEST(package_serializer, serialize_uint64) +{ + constexpr uint64_t kVal = 0x123456789abcdef0ULL; + uint8_t buffer[sizeof(uint64_t)]; + size_t size = comm::PackageSerializer::serialize(buffer, kVal); + EXPECT_EQ(size, sizeof(uint64_t)); + uint8_t expected[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 }; + for (size_t i = 0; i < sizeof(uint64_t); ++i) + { + EXPECT_EQ(buffer[i], expected[i]) << "at index " << i; + } +} + +TEST(package_serializer, serialize_int64) +{ + constexpr int64_t kMinusOne = -1; + uint8_t buffer[sizeof(int64_t)]; + size_t size = comm::PackageSerializer::serialize(buffer, kMinusOne); + EXPECT_EQ(size, sizeof(int64_t)); + uint8_t expected_minus_one[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + for (size_t i = 0; i < sizeof(int64_t); ++i) + { + EXPECT_EQ(buffer[i], expected_minus_one[i]) << "at index " << i; + } + + constexpr int64_t kInt64Max = 0x7fffffffffffffffLL; + size = comm::PackageSerializer::serialize(buffer, kInt64Max); + int64_t decoded; + std::memcpy(&decoded, buffer, sizeof(int64_t)); + decoded = be64toh(decoded); + EXPECT_EQ(decoded, kInt64Max); +} + +TEST(package_serializer, serialize_int64_negative) +{ + constexpr int64_t kVal = -0x123456789abcLL; + uint8_t buffer[sizeof(int64_t)]; + comm::PackageSerializer::serialize(buffer, kVal); + int64_t decoded; + std::memcpy(&decoded, buffer, sizeof(int64_t)); + decoded = be64toh(decoded); + EXPECT_EQ(decoded, kVal); +} + +TEST(package_serializer, serialize_string_empty) +{ + uint8_t buffer[1]; + std::string empty; + size_t size = comm::PackageSerializer::serialize(buffer, empty); + EXPECT_EQ(size, 0u); +} + +TEST(package_serializer, round_trip_int16) +{ + constexpr int16_t kOriginal = -1234; + uint8_t buffer[sizeof(int16_t)]; + comm::PackageSerializer::serialize(buffer, kOriginal); + int16_t tmp; + std::memcpy(&tmp, buffer, sizeof(int16_t)); + int16_t decoded = be16toh(tmp); + EXPECT_EQ(decoded, kOriginal); +} + +TEST(package_serializer, round_trip_uint32) +{ + constexpr uint32_t kOriginal = 0xdeadbeefu; + uint8_t buffer[sizeof(uint32_t)]; + comm::PackageSerializer::serialize(buffer, kOriginal); + uint32_t tmp; + std::memcpy(&tmp, buffer, sizeof(uint32_t)); + uint32_t decoded = be32toh(tmp); + EXPECT_EQ(decoded, kOriginal); +} + +TEST(package_serializer, round_trip_float) +{ + constexpr float kOriginal = 3.14159f; + uint8_t buffer[sizeof(float)]; + comm::PackageSerializer::serialize(buffer, kOriginal); + uint32_t tmp; + std::memcpy(&tmp, buffer, sizeof(uint32_t)); + tmp = be32toh(tmp); + float decoded; + std::memcpy(&decoded, &tmp, sizeof(float)); + EXPECT_FLOAT_EQ(decoded, kOriginal); +} + +TEST(package_serializer, round_trip_double) +{ + constexpr double kOriginal = -1.5e-10; + uint8_t buffer[sizeof(double)]; + comm::PackageSerializer::serialize(buffer, kOriginal); + uint64_t tmp; + std::memcpy(&tmp, buffer, sizeof(uint64_t)); + tmp = be64toh(tmp); + double decoded; + std::memcpy(&decoded, &tmp, sizeof(double)); + EXPECT_DOUBLE_EQ(decoded, kOriginal); } int main(int argc, char* argv[]) diff --git a/tests/test_reverse_interface.cpp b/tests/test_reverse_interface.cpp index bf15fc787..b4fdcb4d1 100644 --- a/tests/test_reverse_interface.cpp +++ b/tests/test_reverse_interface.cpp @@ -29,6 +29,7 @@ // -- END LICENSE BLOCK ------------------------------------------------ #include +#include #include #include #include diff --git a/tests/test_script_command_interface.cpp b/tests/test_script_command_interface.cpp index ae623d463..085b5ab53 100644 --- a/tests/test_script_command_interface.cpp +++ b/tests/test_script_command_interface.cpp @@ -29,6 +29,7 @@ // -- END LICENSE BLOCK ------------------------------------------------ #include +#include #include #include #include "ur_client_library/control/reverse_interface.h" diff --git a/tests/test_script_reader.cpp b/tests/test_script_reader.cpp index 21d949e6e..b9c2e71c3 100644 --- a/tests/test_script_reader.cpp +++ b/tests/test_script_reader.cpp @@ -427,8 +427,8 @@ TEST_F(ScriptReaderTest, DataVariantOperators) EXPECT_THROW((void)(data["bool1"] < data["bool2"]), std::invalid_argument); EXPECT_THROW((void)(data["str1"] > data["str2"]), std::invalid_argument); EXPECT_THROW((void)(data["bool1"] > data["bool2"]), std::invalid_argument); - EXPECT_THROW(data["str1"] == data["bool1"], std::invalid_argument); - EXPECT_THROW(data["double1"] == data["str1"], std::invalid_argument); + EXPECT_THROW((void)(data["str1"] == data["bool1"]), std::invalid_argument); + EXPECT_THROW((void)(data["double1"] == data["str1"]), std::invalid_argument); } TEST_F(ScriptReaderTest, Example) diff --git a/tests/test_trajectory_point_interface.cpp b/tests/test_trajectory_point_interface.cpp index bd843e436..2ed8de37b 100644 --- a/tests/test_trajectory_point_interface.cpp +++ b/tests/test_trajectory_point_interface.cpp @@ -29,6 +29,7 @@ // -- END LICENSE BLOCK ------------------------------------------------ #include +#include #include #include #include