HeartLinked commented on code in PR #361:
URL: https://github.com/apache/iceberg-cpp/pull/361#discussion_r2576165553
##########
src/iceberg/test/rest_catalog_test.cc:
##########
@@ -19,103 +19,206 @@
#include "iceberg/catalog/rest/rest_catalog.h"
+#include <unistd.h>
+
+#include <chrono>
+#include <memory>
+#include <print>
#include <string>
+#include <thread>
#include <unordered_map>
+#include <arpa/inet.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
#include "iceberg/catalog/rest/catalog_properties.h"
+#include "iceberg/result.h"
#include "iceberg/table_identifier.h"
#include "iceberg/test/matchers.h"
+#include "iceberg/test/util/docker_compose_util.h"
namespace iceberg::rest {
-// Test fixture for REST catalog tests, This assumes you have a local REST
catalog service
-// running Default configuration: http://localhost:8181.
-class RestCatalogTest : public ::testing::Test {
+namespace {
+
+constexpr uint16_t kRestCatalogPort = 8181;
+constexpr int kMaxRetries = 60; // Wait up to 60 seconds
+constexpr int kRetryDelayMs = 1000;
+
+constexpr std::string_view kDockerProjectName = "iceberg-rest-catalog-service";
+constexpr std::string_view kCatalogName = "test_catalog";
+constexpr std::string_view kWarehouseName = "default";
+constexpr std::string_view kLocalhostUri = "http://localhost";
+
+/// \brief Check if a localhost port is ready to accept connections
+/// \param port Port number to check
+/// \return true if the port is accessible on localhost, false otherwise
+bool CheckServiceReady(uint16_t port) {
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ return false;
+ }
+
+ struct timeval timeout{
+ .tv_sec = 1,
+ .tv_usec = 0,
+ };
+ setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+ sockaddr_in addr{
+ .sin_family = AF_INET,
+ .sin_port = htons(port),
+ .sin_addr = {.s_addr = htonl(INADDR_LOOPBACK)} // 127.0.0.1
+ };
+ bool result =
+ (connect(sock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))
== 0);
+ close(sock);
+ return result;
+}
+
+} // namespace
+
+/// \brief Integration test fixture for REST catalog with automatic Docker
Compose setup。
+class RestCatalogIntegrationTest : public ::testing::Test {
protected:
- void SetUp() override {
- // Default configuration for local testing
- // You can override this with environment variables if needed
- const char* uri_env = std::getenv("ICEBERG_REST_URI");
- const char* warehouse_env = std::getenv("ICEBERG_REST_WAREHOUSE");
+ static void SetUpTestSuite() {
+ std::string project_name{kDockerProjectName};
+ std::filesystem::path resources_dir =
+ std::filesystem::path(__FILE__).parent_path() / "resources";
+
+ // Create and start DockerCompose
+ docker_compose_ = std::make_unique<DockerCompose>(project_name,
resources_dir);
+ docker_compose_->Up();
+
+ // Wait for REST catalog to be ready on localhost
+ std::println("[INFO] Waiting for REST catalog to be ready at
localhost:{}...",
+ kRestCatalogPort);
+ for (int i = 0; i < kMaxRetries; ++i) {
+ if (CheckServiceReady(kRestCatalogPort)) {
+ std::println("[INFO] REST catalog is ready!");
+ return;
+ }
+ std::println(
+ "[INFO] Waiting for 1s for REST catalog to be ready... (attempt
{}/{})", i + 1,
+ kMaxRetries);
+ std::this_thread::sleep_for(std::chrono::milliseconds(kRetryDelayMs));
+ }
+ throw RestError("REST catalog failed to start within {} seconds",
kMaxRetries);
+ }
- std::string uri = uri_env ? uri_env : "http://localhost:8181";
- std::string warehouse = warehouse_env ? warehouse_env : "default";
+ static void TearDownTestSuite() { docker_compose_.reset(); }
+ void SetUp() override {
config_ = RestCatalogProperties::default_properties();
- config_->Set(RestCatalogProperties::kUri, uri)
- .Set(RestCatalogProperties::kName, std::string("test_catalog"))
- .Set(RestCatalogProperties::kWarehouse, warehouse);
+ config_
+ ->Set(RestCatalogProperties::kUri,
+ std::format("{}:{}", kLocalhostUri, kRestCatalogPort))
+ .Set(RestCatalogProperties::kName, std::string(kCatalogName))
+ .Set(RestCatalogProperties::kWarehouse, std::string(kWarehouseName));
}
void TearDown() override {}
+ /// \brief Helper function to create a REST catalog instance
+ Result<std::unique_ptr<RestCatalog>> CreateCatalog() {
+ return RestCatalog::Make(*config_);
+ }
+
+ static inline std::unique_ptr<DockerCompose> docker_compose_;
std::unique_ptr<RestCatalogProperties> config_;
};
-TEST_F(RestCatalogTest, DISABLED_MakeCatalogSuccess) {
- auto catalog_result = RestCatalog::Make(*config_);
- EXPECT_THAT(catalog_result, IsOk());
+TEST_F(RestCatalogIntegrationTest, MakeCatalogSuccess) {
+ auto catalog_result = CreateCatalog();
+ ASSERT_THAT(catalog_result, IsOk());
- if (catalog_result.has_value()) {
- auto& catalog = catalog_result.value();
- EXPECT_EQ(catalog->name(), "test_catalog");
- }
+ auto& catalog = catalog_result.value();
+ EXPECT_EQ(catalog->name(), kCatalogName);
}
-TEST_F(RestCatalogTest, DISABLED_MakeCatalogEmptyUri) {
- auto invalid_config = RestCatalogProperties::default_properties();
- invalid_config->Set(RestCatalogProperties::kUri, std::string(""));
+TEST_F(RestCatalogIntegrationTest, ListNamespaces) {
+ auto catalog_result = CreateCatalog();
+ ASSERT_THAT(catalog_result, IsOk());
+ auto& catalog = catalog_result.value();
- auto catalog_result = RestCatalog::Make(*invalid_config);
- EXPECT_THAT(catalog_result, IsError(ErrorKind::kInvalidArgument));
- EXPECT_THAT(catalog_result, HasErrorMessage("uri"));
+ Namespace root{.levels = {}};
+ auto result = catalog->ListNamespaces(root);
+ EXPECT_THAT(result, IsOk());
}
-TEST_F(RestCatalogTest, DISABLED_MakeCatalogWithCustomProperties) {
- auto custom_config = RestCatalogProperties::default_properties();
- custom_config
- ->Set(RestCatalogProperties::kUri,
config_->Get(RestCatalogProperties::kUri))
- .Set(RestCatalogProperties::kName,
config_->Get(RestCatalogProperties::kName))
- .Set(RestCatalogProperties::kWarehouse,
- config_->Get(RestCatalogProperties::kWarehouse))
- .Set(RestCatalogProperties::Entry<std::string>{"custom_prop", ""},
- std::string("custom_value"))
- .Set(RestCatalogProperties::Entry<std::string>{"timeout", ""},
- std::string("30000"));
-
- auto catalog_result = RestCatalog::Make(*custom_config);
- EXPECT_THAT(catalog_result, IsOk());
+TEST_F(RestCatalogIntegrationTest, DISABLED_GetNonExistentNamespace) {
+ auto catalog_result = CreateCatalog();
+ ASSERT_THAT(catalog_result, IsOk());
+ auto& catalog = catalog_result.value();
+
+ Namespace ns{.levels = {"test_get_non_existent_namespace"}};
+ auto result = catalog->GetNamespaceProperties(ns);
+
+ EXPECT_THAT(result, HasErrorMessage("does not exist"));
}
-TEST_F(RestCatalogTest, DISABLED_ListNamespaces) {
- auto catalog_result = RestCatalog::Make(*config_);
+TEST_F(RestCatalogIntegrationTest, DISABLED_CreateAndDropNamespace) {
Review Comment:
These methods like CreateNamespace in rest dir are still not implemented now.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]