diff --git a/include/ableton/link/NodeId.hpp b/include/ableton/link/NodeId.hpp index ef4f7981..63d1dff4 100644 --- a/include/ableton/link/NodeId.hpp +++ b/include/ableton/link/NodeId.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace ableton @@ -55,7 +56,18 @@ struct NodeId : NodeIdArray friend std::ostream& operator<<(std::ostream& stream, const NodeId& id) { - return stream << std::string{id.cbegin(), id.cend()}; + const auto flags = stream.flags(); + const auto fill = stream.fill(); + + stream << "0x" << std::hex << std::setfill('0'); + for (const auto byte : id) + { + stream << std::setw(2) << static_cast(byte); + } + + stream.flags(flags); + stream.fill(fill); + return stream; } template diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9836450d..2a665dc9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,7 @@ set(link_core_test_SOURCES ableton/link/tst_LinearRegression.cpp ableton/link/tst_Measurement.cpp ableton/link/tst_Median.cpp + ableton/link/tst_NodeId.cpp ableton/link/tst_Peers.cpp ableton/link/tst_PeerState.cpp ableton/link/tst_Phase.cpp diff --git a/src/ableton/link/tst_NodeId.cpp b/src/ableton/link/tst_NodeId.cpp new file mode 100644 index 00000000..bd87c151 --- /dev/null +++ b/src/ableton/link/tst_NodeId.cpp @@ -0,0 +1,96 @@ +/* Copyright 2025, Ableton AG, Berlin. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you would like to incorporate Link into a proprietary software application, + * please contact . + */ + +#include +#include +#include + +namespace ableton +{ +namespace link +{ + +TEST_CASE("NodeId") +{ + SECTION("StreamState") + { + NodeId nodeId{}; + nodeId.fill(0xAB); + + std::ostringstream stream; + + // Set up some non-default stream state + stream << std::dec << std::setfill('X') << std::setw(5) << 42; + // After setw, width resets to 0, but fill and flags should persist + + // Capture stream state before outputting NodeId + const auto flagsBefore = stream.flags(); + const auto fillBefore = stream.fill(); + + // Output the NodeId + stream << nodeId; + + // Check stream state after outputting NodeId + const auto flagsAfter = stream.flags(); + const auto fillAfter = stream.fill(); + + CHECK(flagsBefore == flagsAfter); + CHECK(fillBefore == fillAfter); + } + + + SECTION("StreamOutputFormat") + { + NodeId nodeId{}; + nodeId.fill(0x00); + nodeId[0] = 0x01; + nodeId[7] = 0xFF; + + std::ostringstream stream; + stream << nodeId; + + CHECK(stream.str() == "0x01000000000000ff"); + } + + SECTION("StreamStateVisual") + { + NodeId nodeId{}; + nodeId.fill(0xAB); + + std::ostringstream stream; + + // Output something before NodeId with specific formatting + stream << std::setfill('_') << std::setw(5) << 42; + CHECK(stream.str() == "___42"); + + // Output the NodeId + stream << " " << nodeId << " "; + + // Now output something after - it should use decimal and default fill + // If stream state is corrupted, this will be in hex and/or use '0' fill + stream << std::setw(5) << 15; + + // Expected: "___42 0xabababababababab ___15" + // If corrupted: "___42 0xabababababababab 0000f" (hex + '0' fill) + CHECK(stream.str() == "___42 0xabababababababab ___15"); + } +} + +} // namespace link +} // namespace ableton