iceberg_test_utils/lib.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! This crate contains common utilities for testing.
19//!
20//! It's not intended for use outside of `iceberg-rust`.
21
22#[cfg(feature = "tests")]
23pub use common::*;
24
25#[cfg(feature = "tests")]
26mod common {
27 use std::sync::Once;
28
29 use iceberg::{Catalog, NamespaceIdent};
30
31 static INIT: Once = Once::new();
32 pub fn set_up() {
33 INIT.call_once(tracing_subscriber::fmt::init);
34 }
35 pub fn normalize_test_name(s: impl ToString) -> String {
36 s.to_string().replace("::", "__").replace('.', "_")
37 }
38
39 // Environment variable names for service endpoints
40 pub const ENV_MINIO_ENDPOINT: &str = "ICEBERG_TEST_MINIO_ENDPOINT";
41 pub const ENV_REST_CATALOG_ENDPOINT: &str = "ICEBERG_TEST_REST_ENDPOINT";
42 pub const ENV_HMS_ENDPOINT: &str = "ICEBERG_TEST_HMS_ENDPOINT";
43 pub const ENV_GLUE_ENDPOINT: &str = "ICEBERG_TEST_GLUE_ENDPOINT";
44 pub const ENV_GCS_ENDPOINT: &str = "ICEBERG_TEST_GCS_ENDPOINT";
45
46 // Default ports matching dev/docker-compose.yaml
47 pub const DEFAULT_MINIO_PORT: u16 = 9000;
48 pub const DEFAULT_REST_CATALOG_PORT: u16 = 8181;
49 pub const DEFAULT_HMS_PORT: u16 = 9083;
50 pub const DEFAULT_GLUE_PORT: u16 = 5001;
51 pub const DEFAULT_GCS_PORT: u16 = 4443;
52
53 /// Returns the MinIO S3-compatible endpoint.
54 /// Checks ICEBERG_TEST_MINIO_ENDPOINT env var, otherwise returns localhost default.
55 pub fn get_minio_endpoint() -> String {
56 std::env::var(ENV_MINIO_ENDPOINT)
57 .unwrap_or_else(|_| format!("http://localhost:{DEFAULT_MINIO_PORT}"))
58 }
59
60 /// Returns the REST catalog endpoint.
61 /// Checks ICEBERG_TEST_REST_ENDPOINT env var, otherwise returns localhost default.
62 pub fn get_rest_catalog_endpoint() -> String {
63 std::env::var(ENV_REST_CATALOG_ENDPOINT)
64 .unwrap_or_else(|_| format!("http://localhost:{DEFAULT_REST_CATALOG_PORT}"))
65 }
66
67 /// Returns the HMS (Hive Metastore) endpoint.
68 /// Checks ICEBERG_TEST_HMS_ENDPOINT env var, otherwise returns localhost default.
69 pub fn get_hms_endpoint() -> String {
70 std::env::var(ENV_HMS_ENDPOINT).unwrap_or_else(|_| format!("localhost:{DEFAULT_HMS_PORT}"))
71 }
72
73 /// Returns the Glue (Moto mock) endpoint.
74 /// Checks ICEBERG_TEST_GLUE_ENDPOINT env var, otherwise returns localhost default.
75 pub fn get_glue_endpoint() -> String {
76 std::env::var(ENV_GLUE_ENDPOINT)
77 .unwrap_or_else(|_| format!("http://localhost:{DEFAULT_GLUE_PORT}"))
78 }
79
80 /// Returns the GCS (fake-gcs-server) endpoint.
81 /// Checks ICEBERG_TEST_GCS_ENDPOINT env var, otherwise returns localhost default.
82 pub fn get_gcs_endpoint() -> String {
83 std::env::var(ENV_GCS_ENDPOINT)
84 .unwrap_or_else(|_| format!("http://localhost:{DEFAULT_GCS_PORT}"))
85 }
86
87 /// Helper to clean up a namespace and its tables before a test runs.
88 /// This handles the case where previous test runs left data in the persistent database.
89 pub async fn cleanup_namespace<C: Catalog>(catalog: &C, ns: &NamespaceIdent) {
90 // Try to drop all tables in the namespace first
91 if let Ok(tables) = catalog.list_tables(ns).await {
92 for table in tables {
93 let _ = catalog.drop_table(&table).await;
94 }
95 }
96 // Then try to drop the namespace itself
97 let _ = catalog.drop_namespace(ns).await;
98 }
99
100 /// Macro to generate a normalized test name with module path prefix.
101 /// Takes one or more string parts and joins them with the module path.
102 ///
103 /// Example:
104 /// ```ignore
105 /// // Returns something like "rest_catalog_test__test_create_table"
106 /// let name = normalize_test_name_with_parts!("test_create_table");
107 ///
108 /// // Returns something like "rest_catalog_test__apple__ios"
109 /// let name = normalize_test_name_with_parts!("apple", "ios");
110 /// ```
111 #[macro_export]
112 macro_rules! normalize_test_name_with_parts {
113 ($($part:expr),+) => {
114 $crate::normalize_test_name([module_path!(), $($part),+].join("_"))
115 };
116 }
117}