This is an automated email from the ASF dual-hosted git repository.
slbotbm pushed a commit to branch cpp-high-level-client-4
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/cpp-high-level-client-4 by
this push:
new 277aa1e90 fixes
277aa1e90 is described below
commit 277aa1e90a30b36b494827f328e9b675fc2da1d2
Author: Rimuksh Kansal <[email protected]>
AuthorDate: Tue Nov 3 01:44:32 2026 +0900
fixes
---
.github/actions/cpp-bazel/pre-merge/action.yml | 1 -
.pre-commit-config.yaml | 11 +++++
foreign/cpp/.bazelrc | 4 ++
foreign/cpp/.bazelversion | 2 +-
foreign/cpp/BUILD.bazel | 29 +++++++++++--
foreign/cpp/MODULE.bazel | 3 ++
foreign/cpp/MODULE.bazel.lock | 10 +++--
foreign/cpp/README.md | 7 +--
foreign/cpp/build.rs | 2 +-
foreign/cpp/include/iggy.hpp | 41 +++++++++++++++---
foreign/cpp/src/client.cpp | 29 +++----------
foreign/cpp/src/type_conversions.cpp | 5 ++-
foreign/cpp/tests/e2e/client.cpp | 8 +++-
foreign/cpp/tests/e2e/partition.cpp | 60 --------------------------
scripts/ci/cpp-coverage.sh | 3 +-
15 files changed, 105 insertions(+), 110 deletions(-)
diff --git a/.github/actions/cpp-bazel/pre-merge/action.yml
b/.github/actions/cpp-bazel/pre-merge/action.yml
index 8913da1c3..0e7044473 100644
--- a/.github/actions/cpp-bazel/pre-merge/action.yml
+++ b/.github/actions/cpp-bazel/pre-merge/action.yml
@@ -96,7 +96,6 @@ runs:
shell: bash
run: |
cd foreign/cpp
- cargo test
../../scripts/ci/cpp-coverage.sh
- name: Stop server after tests
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 92da570fb..694841131 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -208,6 +208,17 @@ repos:
pass_filenames: false
stages: [pre-push]
+ # C++ SDK formatting
+ - repo: local
+ hooks:
+ - id: clang-format
+ name: clang-format (foreign/cpp)
+ entry: clang-format-18
+ args: ["--style=file", "--dry-run", "--Werror"]
+ language: system
+ files: ^foreign/cpp/.*\.(h|hpp|cc|cpp|cxx)$
+ pass_filenames: true
+
# Go SDK formatting
- repo: local
hooks:
diff --git a/foreign/cpp/.bazelrc b/foreign/cpp/.bazelrc
index 880712c20..81b51b249 100644
--- a/foreign/cpp/.bazelrc
+++ b/foreign/cpp/.bazelrc
@@ -20,6 +20,10 @@
# Enable BzlMod
common --enable_bzlmod
+# C++ standard
+build --cxxopt=-std=c++20
+build --host_cxxopt=-std=c++20
+
# Default test behavior
test --test_output=errors
test --cache_test_results=no
diff --git a/foreign/cpp/.bazelversion b/foreign/cpp/.bazelversion
index deeb3d66e..3b7404213 100644
--- a/foreign/cpp/.bazelversion
+++ b/foreign/cpp/.bazelversion
@@ -1 +1 @@
-9.2.0
+9.3.1
diff --git a/foreign/cpp/BUILD.bazel b/foreign/cpp/BUILD.bazel
index 6175a1daf..d99393f78 100644
--- a/foreign/cpp/BUILD.bazel
+++ b/foreign/cpp/BUILD.bazel
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
+load("@bazel_skylib//rules:native_binary.bzl", "native_test")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_import", "cc_library",
"cc_test")
config_setting(
@@ -34,6 +35,7 @@ genrule(
"include/lib.rs.h",
"cxxbridge/rust/cxx.h",
"cxxbridge/sources/lib.rs.cc",
+ "rust_unit_tests",
],
cmd = """
set -euo pipefail
@@ -46,6 +48,7 @@ genrule(
OUT_RS="$$EXECROOT/$(location include/lib.rs.h)"
OUT_CXX="$$EXECROOT/$(location cxxbridge/rust/cxx.h)"
OUT_CC="$$EXECROOT/$(location cxxbridge/sources/lib.rs.cc)"
+ OUT_TESTS="$$EXECROOT/$(location rust_unit_tests)"
PROJECT_ROOT="$$(dirname $$(readlink -f $(location Cargo.toml)))"
cd "$$PROJECT_ROOT"
@@ -61,7 +64,12 @@ genrule(
env -u PWD \
CARGO_TARGET_DIR="$$CARGO_TARGET_DIR" \
RUSTC="$$RUSTC" \
- "$$CARGO" build --quiet $$FLAGS
+ "$$CARGO" build --quiet --lib $$FLAGS
+
+ env -u PWD \
+ CARGO_TARGET_DIR="$$CARGO_TARGET_DIR" \
+ RUSTC="$$RUSTC" \
+ "$$CARGO" rustc --quiet --tests $$FLAGS --
--emit="link=$$OUT_TESTS"
cp "$$CARGO_TARGET_DIR/$$PROFILE/libiggy_cpp.a" "$$OUT_LIB"
@@ -94,6 +102,11 @@ genrule(
],
)
+native_test(
+ name = "rust_unit",
+ src = ":rust_unit_tests",
+)
+
genrule(
name = "extract_profiler_runtime",
outs = ["libprofiler_builtins.a"],
@@ -226,7 +239,7 @@ cc_binary(
)
cc_test(
- name = "unit",
+ name = "cpp_unit",
srcs = glob([
"tests/unit/*.cpp",
]),
@@ -253,8 +266,18 @@ cc_test(
],
)
+test_suite(
+ name = "unit",
+ tests = [
+ ":cpp_unit",
+ ":rust_unit",
+ ],
+)
+
cc_test(
name = "e2e",
+ # The suite already takes about four of the default five minutes.
+ timeout = "long",
srcs = glob([
"tests/e2e/*.cpp",
]) + [
@@ -278,8 +301,6 @@ cc_test(
tags = [
"e2e",
],
- # The suite already takes about four of the default five minutes.
- timeout = "long",
deps = [
":iggy-cpp",
"@googletest//:gtest_main",
diff --git a/foreign/cpp/MODULE.bazel b/foreign/cpp/MODULE.bazel
index 9ea7c4d9b..4a562e42d 100644
--- a/foreign/cpp/MODULE.bazel
+++ b/foreign/cpp/MODULE.bazel
@@ -21,14 +21,17 @@ module(
)
bazel_dep(name = "rules_cc", version = "0.2.26")
+bazel_dep(name = "bazel_skylib", version = "1.9.0")
bazel_dep(name = "platforms", version = "1.1.0")
bazel_dep(name = "googletest", version = "1.18.0.bcr.1")
bazel_dep(name = "cucumber-cpp", version = "0.9.0")
bazel_dep(name = "rules_rust", version = "0.74.0")
bazel_dep(name = "abseil-cpp", version = "20260526.0")
+
bazel_dep(name = "nlohmann_json", version = "3.12.0.bcr.1", dev_dependency =
True)
iggy_source = use_repo_rule("@bazel_tools//tools/build_defs/repo:local.bzl",
"new_local_repository")
+
iggy_source(
name = "iggy_source",
build_file_content = """
diff --git a/foreign/cpp/MODULE.bazel.lock b/foreign/cpp/MODULE.bazel.lock
index 4175f8cbe..53daab76f 100644
--- a/foreign/cpp/MODULE.bazel.lock
+++ b/foreign/cpp/MODULE.bazel.lock
@@ -22,6 +22,7 @@
"https://bcr.bazel.build/modules/apple_support/1.22.1/MODULE.bazel":
"90bd1a660590f3ceffbdf524e37483094b29352d85317060b2327fff8f3f4458",
"https://bcr.bazel.build/modules/apple_support/1.24.1/MODULE.bazel":
"f46e8ddad60aef170ee92b2f3d00ef66c147ceafea68b6877cb45bd91737f5f8",
"https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel":
"0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4",
+ "https://bcr.bazel.build/modules/apple_support/2.5.2/MODULE.bazel":
"bb1b7081e390a8d3885f642cb0073dfcf8e7a36525e079fa8f5835af7079c0fe",
"https://bcr.bazel.build/modules/apple_support/2.8.0/MODULE.bazel":
"c45f5176057092afba0be6c48a9ea02101666802f8be536947e099e94757f8ed",
"https://bcr.bazel.build/modules/apple_support/2.9.1/MODULE.bazel":
"fb209b83ed172af587419acb3340389cfe3260669e5f1c05e1ac3974aca614e0",
"https://bcr.bazel.build/modules/apple_support/2.9.1/source.json":
"247d9f86d94c546533fb01e6e18b018486f9a6dff5faccae8838ef12e659b2a7",
@@ -143,6 +144,7 @@
"https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel":
"b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c",
"https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel":
"eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37",
"https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel":
"353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.15/MODULE.bazel":
"6a0a4a75a57aa6dc888300d848053a58c6b12a29f89d4304e1c41448514ec6e8",
"https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel":
"1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84",
"https://bcr.bazel.build/modules/rules_cc/0.2.18/MODULE.bazel":
"4460ec36adc8f722a6a2a4ac9374cb91f2acebadaa93fc37966129afb3dece87",
"https://bcr.bazel.build/modules/rules_cc/0.2.20/MODULE.bazel":
"f5c07bce5ddcb99be21a0812ff5aadb439e688b7449c6542152363b2fd859c1a",
@@ -236,7 +238,7 @@
"moduleExtensions": {
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions":
{
"general": {
- "bzlTransitiveDigest": "+Kp6j204mBZ3mxlIDDR0gBoP45BZ4jYRhRAcB8sU0qc=",
+ "bzlTransitiveDigest": "WDuVCwqV73DvcHB5Of+02lhUZgPxr9MqtpvMRyUi0eQ=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedInputs": [
"REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools"
@@ -293,7 +295,7 @@
},
"@@rules_python+//python/extensions:config.bzl%config": {
"general": {
- "bzlTransitiveDigest": "dzD8Q2YmrP3fz8saWLHPmlwPLO91ImtTmP/c9JKTStM=",
+ "bzlTransitiveDigest": "L+2ZCpb7GIJqvWaXpzkfk/80d916sIFVmSPzrSm6of8=",
"usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=",
"recordedInputs": [
"REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
@@ -461,7 +463,7 @@
},
"@@rules_python+//python/uv:uv.bzl%uv": {
"general": {
- "bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=",
+ "bzlTransitiveDigest": "IgkgxNrtlAec7OnaFrWoCC5NQhHcY/aIz4jsqcNMm8Y=",
"usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=",
"recordedInputs": [
"REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
@@ -491,7 +493,7 @@
},
"@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": {
"general": {
- "bzlTransitiveDigest": "jgiBS2gw1sTr1ow6fBIqZGzVF1eoi/X+wOnyPnzLxY4=",
+ "bzlTransitiveDigest": "KfVJcoV1nQgI+xL0z3SDxi0TwUOqg22b/BAiyUtmt3U=",
"usagesDigest": "McimNXAztVHDzspa1Kng94T+YeyY/44zx9FkNqIMn2s=",
"recordedInputs": [
"REPO_MAPPING:apple_support+,bazel_skylib bazel_skylib+",
diff --git a/foreign/cpp/README.md b/foreign/cpp/README.md
index 3de19cd2b..dfc1d5be7 100644
--- a/foreign/cpp/README.md
+++ b/foreign/cpp/README.md
@@ -10,7 +10,7 @@
C++ client for [Apache Iggy](https://iggy.apache.org) message streaming.
-Bazel uses the Cargo and Rust toolchain provisioned by `rules_rust`. The Rust
bridge builds locally into a separate target directory in the Bazel output
tree. Use the Bazel version pinned in `.bazelversion` with a compatible Java
runtime (Java 21 or newer for Bazel 9.2.0).
+Bazel uses the Cargo and Rust toolchain provisioned by `rules_rust`. The Rust
bridge builds locally into a separate target directory in the Bazel output
tree. Use the Bazel version pinned in `.bazelversion` with a compatible Java
runtime (Java 21 or newer for Bazel 9.3.1).
Build commands
@@ -18,7 +18,7 @@ Build commands
# Build library
bazel build //:iggy-cpp
-# Unit tests
+# C++ and Rust unit tests
bazel test //:unit
# Low-level integration tests (require a running server)
@@ -99,7 +99,7 @@ The blocking wrapper populates `IggyException::Code()` and
`Kind()` for Rust SDK
errors from these methods:
- `Login`, `Logout`, `ResolveOperation`, and `AbandonOperation`.
-- `CreateUser`, `UpdateUser`, and `DeleteUser`.
+- `CreateUser`, `UpdateUser`, `DeleteUser`, `UpdatePermissions`, and
`ChangePassword`.
- `CreateStream`, `UpdateStream`, and `DeleteStream`.
- `CreateTopic`, `UpdateTopic`, and `DeleteTopic`.
- `CreatePartitions`, `DeletePartitions`, and `DeleteSegments`.
@@ -107,6 +107,7 @@ errors from these methods:
- `StoreConsumerOffset`, `StoreConsumerPosition`, `DeleteConsumerOffset`, and
`DeleteConsumerPosition`.
- `PollMessages`, `PendingPoll::Wait`, `Reader`, and the calls of
`PartitionReader`.
- `GetMetadataChanges`.
+- `SendMessages`, `SendBinaryRequest`, and `SendBinaryRequestToReplica`.
Other methods, including `Connect`, `Disconnect`, and `Shutdown`, report
errors through the exception message only. C++ and bridge-local argument errors
also leave `Code()` and `OperationId()` empty and `Kind()` empty, including for
the methods listed above. `GetMetadataChanges` is the exception: it reports
every invalid query as `invalid_command`, including one the bridge refuses.
diff --git a/foreign/cpp/build.rs b/foreign/cpp/build.rs
index 33b30dd2f..8511b10b7 100644
--- a/foreign/cpp/build.rs
+++ b/foreign/cpp/build.rs
@@ -17,7 +17,7 @@
fn main() {
cxx_build::bridge("src/lib.rs")
- .std("c++17")
+ .std("c++20")
.compile("iggy-cpp-bridge");
println!("cargo:rerun-if-changed=src/client.rs");
diff --git a/foreign/cpp/include/iggy.hpp b/foreign/cpp/include/iggy.hpp
index 1301f002c..ba463e11a 100644
--- a/foreign/cpp/include/iggy.hpp
+++ b/foreign/cpp/include/iggy.hpp
@@ -796,7 +796,7 @@ class Permissions final {
*
* @code{.cpp}
* const auto polled{client.PollMessages(
- * stream, topic, std::nullopt,
+ * stream, topic, 0,
* iggy::Consumer::Group(iggy::Identifier::String("my-group")),
* iggy::PollingStrategy::Next(), 10, true)};
* @endcode
@@ -1041,8 +1041,21 @@ class IggyMessageToSend final {
static IggyMessageToSend Create(std::string_view payload,
std::vector<HeaderEntry> user_headers = {},
absl::uint128 id = 0)
{
- return IggyMessageToSend(id,
std::vector<std::uint8_t>(payload.begin(), payload.end()),
- std::move(user_headers));
+ return Create(std::vector<std::uint8_t>(payload.begin(),
payload.end()), std::move(user_headers), id);
+ }
+
+ /**
+ * @brief Creates a message, taking ownership of the payload and headers.
+ * @param payload Binary message payload. Move it to avoid a copy.
+ * @param user_headers Optional typed user headers. Keys must be unique.
+ * @param id Application-defined message ID.
+ * @return Message owning @p payload and @p user_headers.
+ * @note Payload and header constraints are validated when the message is
sent.
+ */
+ static IggyMessageToSend Create(std::vector<std::uint8_t> payload,
+ std::vector<HeaderEntry> user_headers = {},
+ absl::uint128 id = 0)
{
+ return IggyMessageToSend(id, std::move(payload),
std::move(user_headers));
}
/**
@@ -5973,6 +5986,12 @@ class TransportEndpoints final {
*/
class ClusterNode final {
public:
+ /**
+ * @brief Returns the replica ID used by SendBinaryRequestToReplica().
+ * @return Replica ID advertised by the server.
+ */
+ [[nodiscard]] std::uint8_t ReplicaId() const noexcept { return
replica_id_; }
+
/**
* @brief Returns the configured node name.
* @return Node name owned by this value.
@@ -6004,8 +6023,14 @@ class ClusterNode final {
[[nodiscard]] const std::string &Status() const noexcept { return status_;
}
private:
- ClusterNode(std::string name, std::string ip, TransportEndpoints
endpoints, std::string role, std::string status)
- : name_(std::move(name)),
+ ClusterNode(std::uint8_t replica_id,
+ std::string name,
+ std::string ip,
+ TransportEndpoints endpoints,
+ std::string role,
+ std::string status)
+ : replica_id_(replica_id),
+ name_(std::move(name)),
ip_(std::move(ip)),
endpoints_(endpoints),
role_(std::move(role)),
@@ -6015,6 +6040,7 @@ class ClusterNode final {
friend class ClusterMetadata;
+ std::uint8_t replica_id_;
std::string name_;
std::string ip_;
TransportEndpoints endpoints_;
@@ -6704,7 +6730,7 @@ class IggyConsumer final {
* Rust SDK errors populate IggyException::Code() and IggyException::Kind()
for:
*
* - Login(), Logout(), ResolveOperation(), and AbandonOperation().
- * - CreateUser(), UpdateUser(), and DeleteUser().
+ * - CreateUser(), UpdateUser(), DeleteUser(), UpdatePermissions(), and
ChangePassword().
* - EncryptionKeyFingerprint() and invalid keys passed to CreateStream().
* - CreateStream(), UpdateStream(), and DeleteStream().
* - CreateTopic(), UpdateTopic(), and DeleteTopic().
@@ -6716,6 +6742,7 @@ class IggyConsumer final {
* - PollMessages(), Reader(), StandaloneConsumer(), GroupConsumer(),
* PendingPoll::Wait(), and the calls of PartitionReader and IggyConsumer.
* - GetMetadataChanges().
+ * - SendMessages(), SendBinaryRequest(), and SendBinaryRequestToReplica().
*
* Other methods report errors through the exception message only. C++ and
* bridge-local argument validation failures also have no structured error
@@ -7781,7 +7808,7 @@ class IggyBlockingClient final {
*/
PolledMessages PollMessages(const Identifier &stream,
const Identifier &topic,
- std::optional<std::uint32_t> partition_id,
+ std::uint32_t partition_id,
const Consumer &consumer,
const PollingStrategy &strategy,
std::uint32_t count,
diff --git a/foreign/cpp/src/client.cpp b/foreign/cpp/src/client.cpp
index d10fb0fd4..8dac26dde 100644
--- a/foreign/cpp/src/client.cpp
+++ b/foreign/cpp/src/client.cpp
@@ -580,31 +580,23 @@ SendMessagesResponse
IggyBlockingClient::SendMessages(const Identifier &stream,
for (const auto &message : messages) {
ffi_messages.push_back(message.ToFfi());
}
- rust::Vec<std::uint8_t> ffi_partitioning_value;
- ffi_partitioning_value.reserve(partitioning.Value().size());
- for (const auto byte : partitioning.Value()) {
- ffi_partitioning_value.push_back(byte);
- }
return SendMessagesResponse::FromFfi(
Handle()->send_messages(stream.ToFfi(), topic.ToFfi(),
std::string(partitioning.Kind()),
- std::move(ffi_partitioning_value),
std::move(ffi_messages), error_info));
+ ToFfiBytes(partitioning.Value()),
std::move(ffi_messages), error_info));
});
}
PolledMessages IggyBlockingClient::PollMessages(const Identifier &stream,
const Identifier &topic,
- const
std::optional<std::uint32_t> partition_id,
+ const std::uint32_t
partition_id,
const Consumer &consumer,
const PollingStrategy
&strategy,
const std::uint32_t count,
const bool auto_commit) {
return RethrowAsIggyException([&] {
- if (!partition_id) {
- throw std::invalid_argument("partition_id is required");
- }
const auto options =
PollOptions().SetCount(count).SetCommit(auto_commit ?
CommitPolicy::OnRead : CommitPolicy::Manual);
- return PollMessages(consumer, stream, topic, *partition_id, strategy,
options);
+ return PollMessages(consumer, stream, topic, partition_id, strategy,
options);
});
}
@@ -644,12 +636,7 @@ std::vector<std::uint8_t>
IggyBlockingClient::Snapshot(const SnapshotCompression
std::vector<std::uint8_t> IggyBlockingClient::SendBinaryRequest(std::uint32_t
code,
const
std::vector<std::uint8_t> &payload) {
return RethrowAsIggyException([this, code, &payload](ffi::ErrorInfo
&error_info) {
- rust::Vec<std::uint8_t> ffi_payload;
- ffi_payload.reserve(payload.size());
- for (const auto byte : payload) {
- ffi_payload.push_back(byte);
- }
- auto ffi_response = Handle()->send_binary_request(code,
std::move(ffi_payload), error_info);
+ auto ffi_response = Handle()->send_binary_request(code,
ToFfiBytes(payload), error_info);
return std::vector<std::uint8_t>(ffi_response.begin(),
ffi_response.end());
});
}
@@ -658,13 +645,7 @@ std::vector<std::uint8_t>
IggyBlockingClient::SendBinaryRequestToReplica(std::ui
const
std::vector<std::uint8_t> &payload,
std::uint8_t replica_id) {
return RethrowAsIggyException([this, code, &payload,
replica_id](ffi::ErrorInfo &error_info) {
- rust::Vec<std::uint8_t> ffi_payload;
- ffi_payload.reserve(payload.size());
- for (const auto byte : payload) {
- ffi_payload.push_back(byte);
- }
- auto ffi_response =
- Handle()->send_binary_request_to_replica(code,
std::move(ffi_payload), replica_id, error_info);
+ auto ffi_response = Handle()->send_binary_request_to_replica(code,
ToFfiBytes(payload), replica_id, error_info);
return std::vector<std::uint8_t>(ffi_response.begin(),
ffi_response.end());
});
}
diff --git a/foreign/cpp/src/type_conversions.cpp
b/foreign/cpp/src/type_conversions.cpp
index b9546703a..52207b659 100644
--- a/foreign/cpp/src/type_conversions.cpp
+++ b/foreign/cpp/src/type_conversions.cpp
@@ -868,8 +868,9 @@ TransportEndpoints
TransportEndpoints::FromFfi(ffi::TransportEndpoints endpoints
}
ClusterNode ClusterNode::FromFfi(ffi::ClusterNode node) {
- return ClusterNode(std::string(node.name.c_str(), node.name.size()),
std::string(node.ip.c_str(), node.ip.size()),
- TransportEndpoints::FromFfi(node.endpoints),
std::string(node.role.c_str(), node.role.size()),
+ return ClusterNode(node.replica_id, std::string(node.name.c_str(),
node.name.size()),
+ std::string(node.ip.c_str(), node.ip.size()),
TransportEndpoints::FromFfi(node.endpoints),
+ std::string(node.role.c_str(), node.role.size()),
std::string(node.status.c_str(), node.status.size()));
}
diff --git a/foreign/cpp/tests/e2e/client.cpp b/foreign/cpp/tests/e2e/client.cpp
index 64cb62296..fdce78eea 100644
--- a/foreign/cpp/tests/e2e/client.cpp
+++ b/foreign/cpp/tests/e2e/client.cpp
@@ -2762,6 +2762,7 @@ TEST_F(E2E_Client,
GetClusterMetadataReturnsSingleNodeMetadata) {
ASSERT_EQ(metadata.Nodes().size(), 1u);
const auto &node = metadata.Nodes()[0];
+ EXPECT_EQ(node.ReplicaId(), 0u);
EXPECT_FALSE(node.Name().empty());
EXPECT_FALSE(node.Ip().empty());
EXPECT_EQ(node.Role(), "leader");
@@ -2783,6 +2784,7 @@ TEST_F(E2E_Client,
GetClusterMetadataIsStableAcrossBackToBackCalls) {
const auto &first_node = first_metadata.Nodes()[0];
const auto &second_node = second_metadata.Nodes()[0];
+ EXPECT_EQ(first_node.ReplicaId(), second_node.ReplicaId());
EXPECT_EQ(first_node.Name(), second_node.Name());
EXPECT_EQ(first_node.Ip(), second_node.Ip());
EXPECT_EQ(first_node.Role(), second_node.Role());
@@ -3001,11 +3003,13 @@ TEST_F(E2E_Client,
SendBinaryRequestToReplicaGetStatsReturnsNonEmptyBytes) {
RecordProperty("description",
"Returns a non-empty response body for a raw get-stats
command sent to the server's own replica.");
constexpr std::uint32_t get_stats_command_code = 10;
- constexpr std::uint8_t server_replica_id = 0;
auto client =
GetLoggedInHighLevelClient();
+ const auto metadata =
client.GetClusterMetadata();
+ ASSERT_EQ(metadata.Nodes().size(), 1u);
std::vector<std::uint8_t> response;
- ASSERT_NO_THROW(response =
client.SendBinaryRequestToReplica(get_stats_command_code, {},
server_replica_id));
+ ASSERT_NO_THROW(response =
+
client.SendBinaryRequestToReplica(get_stats_command_code, {},
metadata.Nodes()[0].ReplicaId()));
EXPECT_FALSE(response.empty());
}
diff --git a/foreign/cpp/tests/e2e/partition.cpp
b/foreign/cpp/tests/e2e/partition.cpp
index c0ee41b0e..b271b750d 100644
--- a/foreign/cpp/tests/e2e/partition.cpp
+++ b/foreign/cpp/tests/e2e/partition.cpp
@@ -119,66 +119,6 @@ TEST_F(E2E_Partition,
CreatePartitionsWithUnknownNumericIdentifiersThrows) {
iggy::IggyException);
}
-TEST_F(E2E_Partition, CreatePartitionsWithBoundaryPartitionsCountValues) {
- RecordProperty("description",
- "Accepts supported create_partitions counts and rejects
values outside the allowed range.");
- const std::string stream_name = GetRandomName();
-
- auto client = GetLoggedInHighLevelClient();
-
- ASSERT_NO_THROW(client.CreateStream(stream_name));
- TrackStream(stream_name);
-
- struct TestCase {
- std::string topic_name;
- std::uint32_t partitions_count;
- bool should_succeed;
- std::uint32_t expected_total_partitions;
- };
-
- const std::vector<TestCase> test_cases = {
- {GetRandomName(), static_cast<std::uint32_t>(-1), false, 1},
- {GetRandomName(), 0, false, 1},
- {GetRandomName(), 1, true, 2},
- {GetRandomName(), 43, true, 44},
- {GetRandomName(), 1000, true, 1001},
- {GetRandomName(), 1001, false, 1},
- };
-
- for (const auto &test_case : test_cases) {
- SCOPED_TRACE(test_case.topic_name);
-
ASSERT_NO_THROW(client.CreateTopic(iggy::Identifier::String(stream_name),
test_case.topic_name,
-
iggy::TopicCreateOptions().SetPartitionsCount(1)));
-
- if (test_case.should_succeed) {
-
ASSERT_NO_THROW(client.CreatePartitions(iggy::Identifier::String(stream_name),
-
iggy::Identifier::String(test_case.topic_name),
-
test_case.partitions_count));
- } else {
- ASSERT_THROW(
- client.CreatePartitions(iggy::Identifier::String(stream_name),
-
iggy::Identifier::String(test_case.topic_name), test_case.partitions_count),
- iggy::IggyException);
- }
- }
-
- ASSERT_NO_THROW({
- const auto stream_details =
client.GetStream(iggy::Identifier::String(stream_name));
- ASSERT_EQ(stream_details.Topics().size(), test_cases.size());
- for (const auto &test_case : test_cases) {
- bool found = false;
- for (const auto &topic : stream_details.Topics()) {
- if (topic.Name() == test_case.topic_name) {
- EXPECT_EQ(topic.PartitionsCount(),
test_case.expected_total_partitions);
- found = true;
- break;
- }
- }
- EXPECT_TRUE(found) << "Missing topic " << test_case.topic_name;
- }
- });
-}
-
TEST_F(E2E_Partition, CreatePartitionsWithNumericIdentifiersSucceeds) {
RecordProperty("description",
"Creates partitions successfully when valid numeric stream
and topic identifiers are used.");
diff --git a/scripts/ci/cpp-coverage.sh b/scripts/ci/cpp-coverage.sh
index bb5525c12..6e512b689 100755
--- a/scripts/ci/cpp-coverage.sh
+++ b/scripts/ci/cpp-coverage.sh
@@ -66,8 +66,9 @@ bazel coverage \
sed 's|^SF:|SF:foreign/cpp/|' "$CPP_RAW" >"$OUTPUT"
"$LLVM_COV" export \
- --object bazel-bin/unit \
+ --object bazel-bin/cpp_unit \
--object bazel-bin/e2e \
+ --object bazel-bin/rust_unit_tests \
-instr-profile="$PROFDATA" \
-format=lcov \
-ignore-filename-regex='(\.cargo/|/rustc/|/core/|cxxbridge|/registry/)' |