Skip to content

Commit 7bf668f

Browse files
committed
1
1 parent 61b83ea commit 7bf668f

File tree

9 files changed

+351
-10
lines changed

9 files changed

+351
-10
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
env:
5555
CC: gcc-14
5656
CXX: g++-14
57-
run: ci/scripts/build_iceberg.sh $(pwd)
57+
run: ci/scripts/build_iceberg.sh $(pwd) ON
5858
- name: Build Example
5959
shell: bash
6060
env:
@@ -110,6 +110,7 @@ jobs:
110110
runs-on: ubuntu-24.04
111111
CC: gcc-14
112112
CXX: g++-14
113+
meson-setup-args: -Drest_integration_test=enabled
113114
- title: AMD64 Windows 2025
114115
runs-on: windows-2025
115116
meson-setup-args: --vsenv

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ option(ICEBERG_BUILD_SHARED "Build shared library" OFF)
4242
option(ICEBERG_BUILD_TESTS "Build tests" ON)
4343
option(ICEBERG_BUILD_BUNDLE "Build the battery included library" ON)
4444
option(ICEBERG_BUILD_REST "Build rest catalog client" ON)
45+
option(ICEBERG_BUILD_REST_INTEGRATION_TESTS "Build rest catalog integration tests" OFF)
4546
option(ICEBERG_ENABLE_ASAN "Enable Address Sanitizer" OFF)
4647
option(ICEBERG_ENABLE_UBSAN "Enable Undefined Behavior Sanitizer" OFF)
4748

@@ -60,6 +61,11 @@ else()
6061
set(MSVC_TOOLCHAIN FALSE)
6162
endif()
6263

64+
if(ICEBERG_BUILD_REST_INTEGRATION_TESTS AND WIN32)
65+
set(ICEBERG_BUILD_REST_INTEGRATION_TESTS OFF)
66+
message(WARNING "Cannot build rest integration test on Windows, turning it off.")
67+
endif()
68+
6369
include(CMakeParseArguments)
6470
include(IcebergBuildUtils)
6571
include(IcebergSanitizer)

ci/scripts/build_iceberg.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set -eux
2121

2222
source_dir=${1}
2323
build_dir=${1}/build
24+
build_rest_integration_test=${2:-OFF}
2425

2526
mkdir ${build_dir}
2627
pushd ${build_dir}
@@ -34,6 +35,7 @@ CMAKE_ARGS=(
3435
"-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX:-${ICEBERG_HOME}}"
3536
"-DICEBERG_BUILD_STATIC=ON"
3637
"-DICEBERG_BUILD_SHARED=ON"
38+
"-DICEBERG_BUILD_REST_INTEGRATION_TESTS=${build_rest_integration_test}"
3739
)
3840

3941
if is_windows; then

meson.options

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,12 @@ option(
3636
description: 'Build rest catalog client',
3737
value: 'enabled',
3838
)
39+
40+
option(
41+
'rest_integration_test',
42+
type: 'feature',
43+
description: 'Build integration test for rest catalog',
44+
value: 'disabled',
45+
)
46+
3947
option('tests', type: 'feature', description: 'Build tests', value: 'enabled')

subprojects/cpp-httplib.wrap renamed to src/iceberg/test/resources/docker-compose.yml

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
[wrap-file]
19-
directory = cpp-httplib-0.26.0
20-
source_url = https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.26.0.tar.gz
21-
source_filename = cpp-httplib-0.26.0.tar.gz
22-
source_hash = a66f908f50ccb119769adce44fe1eac75f81b6ffab7c4ac0211bb663ffeb2688
23-
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/cpp-httplib_0.26.0-1/cpp-httplib-0.26.0.tar.gz
24-
wrapdb_version = 0.26.0-1
18+
networks:
19+
rest_bridge:
2520

26-
[provide]
27-
dependency_names = cpp-httplib
21+
services:
22+
rest:
23+
image: apache/iceberg-rest-fixture:1.10.0
24+
environment:
25+
- AWS_ACCESS_KEY_ID=admin
26+
- AWS_SECRET_ACCESS_KEY=password
27+
- AWS_REGION=us-east-1
28+
- CATALOG_CATALOG__IMPL=org.apache.iceberg.jdbc.JdbcCatalog
29+
- CATALOG_URI=jdbc:sqlite:file:/tmp/iceberg_rest_mode=memory
30+
- CATALOG_WAREHOUSE=file:///tmp/iceberg_warehouse
31+
networks:
32+
rest_bridge:
33+
ports:
34+
- "8181:8181"

src/iceberg/test/util/cmd_util.cc

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include "iceberg/test/util/cmd_util.h"
21+
22+
#include <unistd.h>
23+
24+
#include <array>
25+
#include <cstring>
26+
#include <format>
27+
#include <iostream>
28+
#include <print>
29+
#include <stdexcept>
30+
31+
#include <sys/wait.h>
32+
33+
namespace iceberg {
34+
35+
Command::Command(std::string program) : program_(std::move(program)) {}
36+
37+
Command& Command::Arg(std::string a) {
38+
args_.push_back(std::move(a));
39+
return *this;
40+
}
41+
42+
Command& Command::Args(const std::vector<std::string>& as) {
43+
args_.insert(args_.end(), as.begin(), as.end());
44+
return *this;
45+
}
46+
47+
Command& Command::CurrentDir(const std::filesystem::path& path) {
48+
cwd_ = path;
49+
return *this;
50+
}
51+
52+
Command& Command::Env(const std::string& key, const std::string& val) {
53+
env_vars_[key] = val;
54+
return *this;
55+
}
56+
57+
void Command::RunCommand(const std::string& desc) const {
58+
std::println("[INFO] Starting to {}, command: {} {}", desc, program_, fmt_args());
59+
60+
std::cout.flush();
61+
std::cerr.flush();
62+
63+
pid_t pid = fork();
64+
65+
if (pid == -1) {
66+
std::println(stderr, "[ERROR] Fork failed: {}", std::strerror(errno));
67+
throw std::runtime_error(std::format("Fork failed: {}", std::strerror(errno)));
68+
}
69+
70+
// --- Child Process ---
71+
if (pid == 0) {
72+
if (!cwd_.empty()) {
73+
std::error_code ec;
74+
std::filesystem::current_path(cwd_, ec);
75+
if (ec) {
76+
std::println(stderr, "Failed to change directory to '{}': {}", cwd_.string(),
77+
ec.message());
78+
_exit(126); // Command invoked cannot execute
79+
}
80+
}
81+
82+
for (const auto& [k, v] : env_vars_) {
83+
setenv(k.c_str(), v.c_str(), 1);
84+
}
85+
86+
std::vector<char*> argv;
87+
argv.reserve(args_.size() + 2);
88+
argv.push_back(const_cast<char*>(program_.c_str()));
89+
90+
for (const auto& arg : args_) {
91+
argv.push_back(const_cast<char*>(arg.c_str()));
92+
}
93+
argv.push_back(nullptr);
94+
95+
execvp(program_.c_str(), argv.data());
96+
97+
std::println(stderr, "execvp failed: {}", std::strerror(errno));
98+
_exit(127);
99+
}
100+
101+
// --- Parent Process ---
102+
int status = 0;
103+
if (waitpid(pid, &status, 0) == -1) {
104+
std::println(stderr, "[ERROR] waitpid failed: {}", std::strerror(errno));
105+
throw std::runtime_error(std::format("waitpid failed: {}", std::strerror(errno)));
106+
}
107+
108+
int exit_code = -1;
109+
if (WIFEXITED(status)) {
110+
exit_code = WEXITSTATUS(status);
111+
} else if (WIFSIGNALED(status)) {
112+
exit_code = 128 + WTERMSIG(status);
113+
}
114+
115+
if (exit_code == 0) {
116+
std::println("[INFO] {} succeed!", desc);
117+
return;
118+
} else {
119+
std::println(stderr, "[ERROR] {} failed. Exit code: {}", desc, exit_code);
120+
throw std::runtime_error(
121+
std::format("{} failed with exit code: {}", desc, exit_code));
122+
}
123+
}
124+
125+
std::string Command::fmt_args() const {
126+
std::string s;
127+
for (const auto& a : args_) {
128+
s += a + " ";
129+
}
130+
return s;
131+
}
132+
133+
} // namespace iceberg

src/iceberg/test/util/cmd_util.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#pragma once
21+
22+
#include <filesystem>
23+
#include <map>
24+
#include <string>
25+
#include <vector>
26+
27+
/// \file iceberg/test/util/cmd_util.h
28+
/// Utilities for building and executing shell commands in tests.
29+
30+
namespace iceberg {
31+
32+
/// \brief A shell command builder and executor for tests.
33+
class Command {
34+
public:
35+
explicit Command(std::string program);
36+
37+
/// \brief Add a single argument
38+
Command& Arg(std::string a);
39+
40+
/// \brief Add multiple arguments at once
41+
Command& Args(const std::vector<std::string>& as);
42+
43+
/// \brief Set the current working directory for the command
44+
Command& CurrentDir(const std::filesystem::path& path);
45+
46+
/// \brief Set an environment variable for the command
47+
Command& Env(const std::string& key, const std::string& val);
48+
49+
/// \brief Execute the command and print logs
50+
/// \return A Status indicating success or failure
51+
void RunCommand(const std::string& desc) const;
52+
53+
private:
54+
std::string program_;
55+
std::vector<std::string> args_;
56+
std::filesystem::path cwd_;
57+
std::map<std::string, std::string> env_vars_;
58+
59+
/// \brief Format arguments for logging
60+
std::string fmt_args() const;
61+
};
62+
63+
} // namespace iceberg
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include "iceberg/test/util/docker_compose_util.h"
21+
22+
#include <cctype>
23+
24+
#include "iceberg/test/util/cmd_util.h"
25+
26+
namespace iceberg {
27+
28+
DockerCompose::DockerCompose(std::string project_name,
29+
std::filesystem::path docker_compose_dir)
30+
: project_name_(std::move(project_name)),
31+
docker_compose_dir_(std::move(docker_compose_dir)) {}
32+
33+
DockerCompose::~DockerCompose() { Down(); }
34+
35+
void DockerCompose::Up() {
36+
auto cmd = BuildDockerCommand({"up", "-d", "--wait", "--timeout", "60"});
37+
return cmd.RunCommand("docker compose up");
38+
}
39+
40+
void DockerCompose::Down() {
41+
auto cmd = BuildDockerCommand({"down", "-v", "--remove-orphans"});
42+
return cmd.RunCommand("docker compose down");
43+
}
44+
45+
Command DockerCompose::BuildDockerCommand(const std::vector<std::string>& args) const {
46+
Command cmd("docker");
47+
// Set working directory
48+
cmd.CurrentDir(docker_compose_dir_);
49+
// Use 'docker compose' subcommand with project name
50+
cmd.Arg("compose").Arg("-p").Arg(project_name_).Args(args);
51+
return cmd;
52+
}
53+
54+
} // namespace iceberg

0 commit comments

Comments
 (0)