fix tests
diff --git a/foreign/cpp/include/iggy.hpp b/foreign/cpp/include/iggy.hpp index 22906c6..19dc07b 100644 --- a/foreign/cpp/include/iggy.hpp +++ b/foreign/cpp/include/iggy.hpp
@@ -1073,7 +1073,7 @@ * `DEFAULT_PARTITIONS_COUNT` (1). * @note Not an option key. Fills the `CreateTopic` command's fixed field; * it is consumed to compute assignments and is not stored as a topic - * option. Must be `1..=1000` when set; server rejects `0`. + * option. Must be `0..=1000` when set. */ std::optional<std::uint32_t> PartitionsCount() const noexcept { return partitions_count_; } TopicCreateOptions &SetPartitionsCount(std::uint32_t partitions_count) noexcept { @@ -1100,11 +1100,16 @@ * `IggyExpiry::ServerDefault` (alias `never_expire` with sentinel * `u64::MAX` on the wire as `Uint64`). * @note Catalog key `message_expiry` (`Uint64` micros, or `String` like - * `"7 days"` via `Raw`). `0` normalizes to `nullopt`. Also updatable. + * `"7 days"` via `Raw`). `ServerDefault()` normalizes to `nullopt`. + * Also updatable. */ std::optional<::iggy::Expiry> MessageExpiry() const noexcept { return message_expiry_; } TopicCreateOptions &SetMessageExpiry(::iggy::Expiry message_expiry) { - message_expiry_ = std::move(message_expiry); + if (message_expiry.ExpiryKind() == "server_default") { + message_expiry_.reset(); + } else { + message_expiry_ = std::move(message_expiry); + } return *this; } @@ -1113,12 +1118,17 @@ * @return Max size when set; `nullopt` uses the server default * `MaxTopicSize::ServerDefault` (`unlimited`, `u64::MAX` on wire). * @note Catalog key `max_topic_size` (`Uint64` bytes or `String` like - * `"1 GiB"` via `Raw`). `0` normalizes to `nullopt`. Must be `>=` - * the resolved segment size when both are set. Also updatable. + * `"1 GiB"` via `Raw`). `ServerDefault()` normalizes to `nullopt`. + * Must be `>=` the resolved segment size when both are set. Also + * updatable. */ std::optional<::iggy::MaxTopicSize> MaxTopicSize() const noexcept { return max_topic_size_; } TopicCreateOptions &SetMaxTopicSize(::iggy::MaxTopicSize max_topic_size) { - max_topic_size_ = std::move(max_topic_size); + if (max_topic_size.MaxTopicSizeValue() == "server_default") { + max_topic_size_.reset(); + } else { + max_topic_size_ = std::move(max_topic_size); + } return *this; } @@ -1269,11 +1279,15 @@ * @brief New message retention policy. * @return Expiry when set; `nullopt` keeps the current value. * @note Catalog key `message_expiry` (`Uint64` micros or `String` like - * `"7 days"` via `Raw`). `0` is treated as `nullopt` on the Rust side. + * `"7 days"` via `Raw`). `ServerDefault()` normalizes to `nullopt`. */ std::optional<::iggy::Expiry> MessageExpiry() const noexcept { return message_expiry_; } TopicUpdateOptions &SetMessageExpiry(::iggy::Expiry message_expiry) { - message_expiry_ = std::move(message_expiry); + if (message_expiry.ExpiryKind() == "server_default") { + message_expiry_.reset(); + } else { + message_expiry_ = std::move(message_expiry); + } return *this; } @@ -1281,11 +1295,15 @@ * @brief New maximum retained topic size. * @return Max size when set; `nullopt` keeps the current value. * @note Catalog key `max_topic_size` (`Uint64` bytes or `String` like - * `"1 GiB"` via `Raw`). `0` is treated as `nullopt` on the Rust side. + * `"1 GiB"` via `Raw`). `ServerDefault()` normalizes to `nullopt`. */ std::optional<::iggy::MaxTopicSize> MaxTopicSize() const noexcept { return max_topic_size_; } TopicUpdateOptions &SetMaxTopicSize(::iggy::MaxTopicSize max_topic_size) { - max_topic_size_ = std::move(max_topic_size); + if (max_topic_size.MaxTopicSizeValue() == "server_default") { + max_topic_size_.reset(); + } else { + max_topic_size_ = std::move(max_topic_size); + } return *this; }
diff --git a/foreign/cpp/tests/e2e/topic.cpp b/foreign/cpp/tests/e2e/topic.cpp index 5b2355e..916b433 100644 --- a/foreign/cpp/tests/e2e/topic.cpp +++ b/foreign/cpp/tests/e2e/topic.cpp
@@ -124,21 +124,21 @@ ASSERT_THROW(client.CreateTopic(iggy::Identifier::String(stream_name), overflow_topic_name, iggy::TopicCreateOptions().SetPartitionsCount(1001)), std::exception); - ASSERT_THROW(client.CreateTopic(iggy::Identifier::String(stream_name), zero_partitions_topic_name, - iggy::TopicCreateOptions().SetPartitionsCount(0)), - std::exception); + ASSERT_NO_THROW(client.CreateTopic(iggy::Identifier::String(stream_name), zero_partitions_topic_name, + iggy::TopicCreateOptions().SetPartitionsCount(0))); const auto stream_details = client.GetStream(iggy::Identifier::String(stream_name)); - EXPECT_EQ(stream_details.TopicsCount(), 2u); + EXPECT_EQ(stream_details.TopicsCount(), 3u); std::unordered_map<std::string, std::uint32_t> topic_partitions; for (const auto &topic : stream_details.Topics()) { topic_partitions[topic.Name()] = topic.PartitionsCount(); } - EXPECT_EQ(topic_partitions.size(), 2u); + EXPECT_EQ(topic_partitions.size(), 3u); EXPECT_EQ(topic_partitions[default_partitions_topic], 1u); EXPECT_EQ(topic_partitions[max_partitions_topic_name], 1000u); + EXPECT_EQ(topic_partitions[zero_partitions_topic_name], 0u); } TEST_F(E2E_Topic, CreateTopicWithInvalidNamesThrows) { @@ -648,25 +648,22 @@ } TEST_F(E2E_Topic, GetTopicReturnsEmptyPartitionsForZeroPartitionTopic) { - RecordProperty("description", "Rejects zero partitions and creates a topic with the default partition count."); + RecordProperty("description", "Returns an empty partitions vector for a topic created with zero partitions."); const std::string stream_name = GetRandomName(); const std::string topic_name = GetRandomName(); - const std::string zero_topic = GetRandomName(); auto client = GetLoggedInHighLevelClient(); ASSERT_NO_THROW(client.CreateStream(stream_name)); TrackStream(stream_name); - ASSERT_THROW(client.CreateTopic(iggy::Identifier::String(stream_name), zero_topic, - iggy::TopicCreateOptions().SetPartitionsCount(0)), - std::exception); - ASSERT_NO_THROW(client.CreateTopic(iggy::Identifier::String(stream_name), topic_name, iggy::TopicCreateOptions())); + ASSERT_NO_THROW(client.CreateTopic(iggy::Identifier::String(stream_name), topic_name, + iggy::TopicCreateOptions().SetPartitionsCount(0))); ASSERT_NO_THROW({ const auto topic_details = client.GetTopic(iggy::Identifier::String(stream_name), iggy::Identifier::String(topic_name)); EXPECT_EQ(topic_details.Name(), topic_name); - EXPECT_EQ(topic_details.PartitionsCount(), 1u); - EXPECT_EQ(topic_details.Partitions().size(), 1u); + EXPECT_EQ(topic_details.PartitionsCount(), 0u); + EXPECT_TRUE(topic_details.Partitions().empty()); }); }
diff --git a/foreign/cpp/tests/unit/unit_tests.cpp b/foreign/cpp/tests/unit/unit_tests.cpp index e8628f4..6f3eb10 100644 --- a/foreign/cpp/tests/unit/unit_tests.cpp +++ b/foreign/cpp/tests/unit/unit_tests.cpp
@@ -204,6 +204,17 @@ EXPECT_EQ(options.MaxTopicSize()->MaxTopicSizeValue(), "1024"); } +TEST(TopicCreateOptionsTest, ServerDefaultSentinelsClearValues) { + iggy::TopicCreateOptions options; + options.SetMessageExpiry(iggy::Expiry::Duration(15)).SetMaxTopicSize(iggy::MaxTopicSize::FromBytes(1024)); + ASSERT_TRUE(options.MessageExpiry().has_value()); + ASSERT_TRUE(options.MaxTopicSize().has_value()); + + options.SetMessageExpiry(iggy::Expiry::ServerDefault()).SetMaxTopicSize(iggy::MaxTopicSize::ServerDefault()); + EXPECT_FALSE(options.MessageExpiry().has_value()); + EXPECT_FALSE(options.MaxTopicSize().has_value()); +} + TEST(TopicCreateOptionsTest, RawMapStoresForwardCompatibleKeys) { iggy::TopicCreateOptions options; options.SetRawEntries({{"custom_key", "custom_value"}}); @@ -235,6 +246,17 @@ EXPECT_EQ(options.MaxTopicSize()->MaxTopicSizeValue(), "unlimited"); } +TEST(TopicUpdateOptionsTest, ServerDefaultSentinelsClearValues) { + iggy::TopicUpdateOptions options; + options.SetMessageExpiry(iggy::Expiry::Duration(15)).SetMaxTopicSize(iggy::MaxTopicSize::FromBytes(1024)); + ASSERT_TRUE(options.MessageExpiry().has_value()); + ASSERT_TRUE(options.MaxTopicSize().has_value()); + + options.SetMessageExpiry(iggy::Expiry::ServerDefault()).SetMaxTopicSize(iggy::MaxTopicSize::ServerDefault()); + EXPECT_FALSE(options.MessageExpiry().has_value()); + EXPECT_FALSE(options.MaxTopicSize().has_value()); +} + TEST(TopicUpdateOptionsTest, RawMapStoresKeys) { iggy::TopicUpdateOptions options; options.SetRawEntries({{"message_expiry", "7 days"}});