diff --git a/CMakeLists.txt b/CMakeLists.txt index 14a4c5e..10a39b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ include(CTest) add_subdirectory(testcontainers-bridge) add_subdirectory(testcontainers-c) +add_subdirectory(testcontainers-cpp) add_subdirectory(modules) if(NOT DEFINED SKIP_DEMOS) add_subdirectory(demo) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bbc49c1..38ea6e4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ cmake -DSKIP_DEMOS=true . ## Contributing to the Documentation The documentation is structured in the MkDocs format and uses Material for MkDocs. -To develop the site in this repository, start it in the [Dev Containers](.devcontainer/README.md) +To develop the site in this repository, start it in a [Dev Container](.devcontainer/README.md) and use the following commands: ```shell @@ -57,4 +57,4 @@ mkdocs build - `tc_` is used as a prefix for all exported Testcontainers functions - When possible, we try to avoid special Golang types in public API and try to expose wrapper types - `const` is important for users, and please add it to your arguments when possible. - There is no Const in Golang, so some `typedef` injection is needed when importing CGo + There is no `const` in Golang, so some `typedef` injection is needed when importing CGo diff --git a/README.md b/README.md index 9f8a53e..44d4af3 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,8 @@ [![Stability: Experimental](https://masterminds.github.io/stability/experimental.svg)](https://masterminds.github.io/stability/experimental.html) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/oleg-nenashev/testcontainers-c)](https://github.com/oleg-nenashev/testcontainers-c/releases) -!!! warning - This is a prototype. - There is a lot to do before it can be distributed and used in production, see the GitHub Issues - and the [project roadmap](./ROADMAP.md) +> [!WARNING] +> This is a prototype. There is a lot to do before it can be distributed and used in production, see the GitHub Issues and the [project roadmap](./ROADMAP.md) This is not a standalone [Testcontainers](https://testcontainers.org/) engine, but a C-style shared library adapter for native languages like C/C++, D, Lua, Swift, etc. @@ -88,9 +86,7 @@ describes how it can be done in principle. ## Credits Using a complex Golang framework from C/C++ is not trivial. -Neither the CMake files are. -This project would not succeed without many quality articles -and help from the community. +Neither are the CMake files. This project would not succeed without many quality articles and help from the community. Kudos to: @@ -102,7 +98,7 @@ Kudos to: [An Adventure into CGO - Calling Go code with C](https://medium.com/@ben.mcclelland/an-adventure-into-cgo-calling-go-code-with-c-b20aa6637e75) - [Insu Jang](https://github.com/insujang) for [Implementing Kubernetes C++ Client Library using Go Client Library](https://insujang.github.io/2019-11-28/implementing-kubernetes-cpp-client-library) -- Infinite number of StackOverflow contributors +- An infinite number of StackOverflow contributors ## Discuss diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 3b46c2c..d516a0c 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(generic-container) add_subdirectory(wiremock) add_subdirectory(google-test) +add_subdirectory(google-test-cpp) diff --git a/demo/google-test-cpp/CMakeLists.txt b/demo/google-test-cpp/CMakeLists.txt new file mode 100644 index 0000000..1e4a440 --- /dev/null +++ b/demo/google-test-cpp/CMakeLists.txt @@ -0,0 +1,32 @@ +# Google Test demo +# This is based on https://google.github.io/googletest/quickstart-cmake.html +cmake_minimum_required (VERSION 3.26) +project (google-test-cpp-demo + VERSION 0.1.0 + DESCRIPTION "Demonstrates usage of Testcontainers C++ in Google Test" + LANGUAGES CXX +) + +set(TARGET_OUT ${PROJECT_NAME}.out) + +# GoogleTest requires at least C++14 +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.17.0 +) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +enable_testing() +file(COPY test_data DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(${TARGET_OUT} test.cpp) +target_link_libraries(${TARGET_OUT} PRIVATE testcontainers-cpp) +target_link_libraries(${TARGET_OUT} PRIVATE GTest::gtest_main) + +include(GoogleTest) +gtest_discover_tests(${TARGET_OUT}) diff --git a/demo/google-test-cpp/README.md b/demo/google-test-cpp/README.md new file mode 100644 index 0000000..f5b9bd5 --- /dev/null +++ b/demo/google-test-cpp/README.md @@ -0,0 +1,13 @@ +# Using Testcontainers C++ in Google Test + +Demonstrates usage of Testcontainers C++ in [Google +Test](https://github.com/google/googletest). See +[test.cpp](./test.cpp) for the code. + +## Run the demo + +```bash +cmake -S . -B /tmp/tc-native +cmake --build /tmp/tc-native/ +ctest --output-on-failure -R Class +``` diff --git a/demo/google-test-cpp/test.cpp b/demo/google-test-cpp/test.cpp new file mode 100644 index 0000000..13f1b70 --- /dev/null +++ b/demo/google-test-cpp/test.cpp @@ -0,0 +1,54 @@ +#include + +#include +#include + +#include "testcontainers.hpp" + +using namespace testcontainers; + +class WireMockTestContainerClass : public ::testing::Test { + const char* WIREMOCK_IMAGE = "wiremock/wiremock:3.0.1-1"; + const char* WIREMOCK_ADMIN_MAPPING_ENDPOINT = "/__admin/mappings"; + +protected: + void SetUp() override { + using namespace std::literals; + + builder.expose_port(TcpPort{8080}).wait_for_http(TcpPort{8080}, WIREMOCK_ADMIN_MAPPING_ENDPOINT); + } + + Container::Builder builder = Container::Builder{WIREMOCK_IMAGE}; +}; + +/// This test runs a "Hello World" example. +TEST_F(WireMockTestContainerClass, HelloWorld) { + auto container = builder.with_file("test_data/hello.json", "/home/wiremock/mappings/hello.json").build(); + ASSERT_TRUE(container.has_value()) << "Failed to run the container"; + + auto [code, response] = container->send_http(HttpMethod::Get, TcpPort{8080}, "/hello"); + ASSERT_EQ(code, 200) << "Expected 200 OK. Received response: " << response; +} + +/// This test responds to an HTTP request with response from a +/// prepared file. +TEST_F(WireMockTestContainerClass, HelloWorldFromResource) { + auto container = builder.with_file("test_data/hello_with_resource.json", "/home/wiremock/mappings/hello2.json") + .with_file("test_data/response.xml", "/home/wiremock/__files/response.xml") + .build(); + ASSERT_TRUE(container.has_value()) << "Failed to run the container"; + + auto [code, response] = container->send_http(HttpMethod::Get, TcpPort{8080}, "/hello-from-resource"); + ASSERT_EQ(code, 200) << "Expected 200 OK. Received response: " << response; +} + +/// This test performs a request that is guaranteed to fail and +/// return an HTTP-500. +TEST_F(WireMockTestContainerClass, HelloWorldFromMissingResource) { + auto container = + builder.with_file("test_data/hello_with_missing_resource.json", "/home/wiremock/mappings/hello3.json").build(); + ASSERT_TRUE(container.has_value()) << "Failed to run the container"; + + auto [code, response] = container->send_http(HttpMethod::Get, TcpPort{8080}, "/hello-from-missing-resource"); + ASSERT_EQ(code, 500) << "Expected 500 Internal Server Error. Received response: " << response; +} diff --git a/demo/google-test-cpp/test_data/hello.json b/demo/google-test-cpp/test_data/hello.json new file mode 100644 index 0000000..0525333 --- /dev/null +++ b/demo/google-test-cpp/test_data/hello.json @@ -0,0 +1,12 @@ +{ + "request": { + "method": "GET", + "url": "/hello" + }, + + "response": { + "status": 200, + "body": "Hello, world!" + } + } + \ No newline at end of file diff --git a/demo/google-test-cpp/test_data/hello_with_missing_resource.json b/demo/google-test-cpp/test_data/hello_with_missing_resource.json new file mode 100644 index 0000000..cf6abd2 --- /dev/null +++ b/demo/google-test-cpp/test_data/hello_with_missing_resource.json @@ -0,0 +1,10 @@ +{ + "request": { + "method": "GET", + "url": "/hello-from-missing-resource" + }, + "response": { + "status": 200, + "bodyFileName": "response_missing.xml" + } +} diff --git a/demo/google-test-cpp/test_data/hello_with_resource.json b/demo/google-test-cpp/test_data/hello_with_resource.json new file mode 100644 index 0000000..afe6f7e --- /dev/null +++ b/demo/google-test-cpp/test_data/hello_with_resource.json @@ -0,0 +1,10 @@ +{ + "request": { + "method": "GET", + "url": "/hello-from-resource" + }, + "response": { + "status": 200, + "bodyFileName": "response.xml" + } +} diff --git a/demo/google-test-cpp/test_data/response.xml b/demo/google-test-cpp/test_data/response.xml new file mode 100644 index 0000000..33c5aef --- /dev/null +++ b/demo/google-test-cpp/test_data/response.xml @@ -0,0 +1,6 @@ + + you + WireMock + Response + Hello, world! + diff --git a/docs/SUPPORT.md b/docs/SUPPORT.md index 1cfbfac..7263e77 100644 --- a/docs/SUPPORT.md +++ b/docs/SUPPORT.md @@ -13,17 +13,13 @@ At the moment, this is single channel for all project matters. ## Raising Issues and Feature Requests -Use [GitHub Issues](https://github.com/testcontainers/testcontainers-c/issues). +Use [GitHub Issues](https://github.com/testcontainers/testcontainers-native/issues). Note that it may take some time to get a response, thanks for your patience. Contributions are always welcome, see the [Contributor Guide](../CONTRIBUTING.md). ## Reporting Security Issues -You can submit any security issue or suspected vulnerability -on [GitHub Security](https://github.com/testcontainers/testcontainers-c/security/advisories). -Please do NOT use public GitHub Issues for reporting vulnerabilities. - -Read More - [Security Policy](./SECURITY.md). +See the [Security Policy](./SECURITY.md). ## Commercial Support and Customization diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 73fa218..1476f99 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -1,8 +1,7 @@ # Architecture -!!! note - This section is coming soon. - All contributions are welcome, just submit a pull request! +> [!NOTE] +> This section is coming soon. All contributions are welcome, just submit a pull request! ## Build Process diff --git a/docs/c/README.md b/docs/c/README.md index b6a29de..33ca908 100644 --- a/docs/c/README.md +++ b/docs/c/README.md @@ -3,9 +3,8 @@ You can use the `testcontainers-c` library with common C unit testing frameworks and, soon, with package managers. -!!! note - This section is coming soon. - All contributions are welcome, just submit a pull request! +> [!NOTE] +> This section is coming soon. All contributions are welcome, just submit a pull request! ## Installing the library @@ -39,9 +38,8 @@ CPMAddPackage( ## Using the Library -!!! note - More frameworks will be documented soon. - All contributions are welcome, just submit a pull request! +> [!NOTE] +> More frameworks will be documented soon. All contributions are welcome, just submit a pull request! ### CMake Tests (CTest) diff --git a/docs/cpp/README.md b/docs/cpp/README.md index c0913ed..43ffe30 100644 --- a/docs/cpp/README.md +++ b/docs/cpp/README.md @@ -2,7 +2,7 @@ At the moment, there is no dedicated C++ binding library/header, but it is on [our roadmap](../../ROADMAP.md). -Tou can use the `testcontainers-c` library directly +You can use the `testcontainers-c` library directly in all C++ testing frameworks. ## Google Test @@ -29,10 +29,10 @@ protected: tc_with_exposed_tcp_port(requestId, 8080); tc_with_wait_for_http(requestId, 8080, WIREMOCK_ADMIN_MAPPING_ENDPOINT); tc_with_file(requestId, "test_data/hello.json", "/home/wiremock/mappings/hello.json"); - + struct tc_run_container_return ret = tc_run_container(requestId); containerId = ret.r0; - + EXPECT_TRUE(ret.r1) << "Failed to run the container: " << ret.r2; }; @@ -51,10 +51,10 @@ Then, you can define new tests by referring to the container via `containerId`. TEST_F(WireMockTestContainer, HelloWorld) { std::cout << "Sending HTTP request to the container\n"; struct tc_send_http_get_return response = tc_send_http_get(containerId, 8080, "/hello"); - + ASSERT_NE(response.r0, -1) << "Failed to send HTTP request: " << response.r2; ASSERT_EQ(response.r0, 200) << "Received wrong response code: " << response.r1 << response.r2; - + std::cout << "Server Response: HTTP-" << response.r0 << '\n' << response.r1 << '\n'; } ``` diff --git a/docs/getting-started.md b/docs/getting-started.md index ded08ff..654c245 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,13 +1,12 @@ # Getting Started with Testcontainers for C/C++ -In this section, we will build a demo C application that uses Testcontainers -in a simple C application -for deploying a [WireMock](https://wiremock.org/) API server, -sends a simple HTTP request to this service, +In this section, we will build a simple demo C application that uses Testcontainers +for deploying a [WireMock](https://wiremock.org/) API server. +It sends a simple HTTP request to this service, and verifies the response. -We will not be using any C/C++ test framework for that. +We will not be using any test framework for that. -For test framework framework examples, see the [demos](../demo/README.md). +For test framework examples, see the [demos](../demo/README.md). ## Build the Project diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..6005341 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1754498491, + "narHash": "sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "c2ae88e026f9525daf89587f3cbee584b92b6134", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..04527a2 --- /dev/null +++ b/flake.nix @@ -0,0 +1,24 @@ +{ + description = "Testcontainers Native"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + }; + + outputs = { self, nixpkgs }: let + system = "x86_64-linux"; + pkgs = import nixpkgs { inherit system; }; + in { + devShells.${system}.default = pkgs.mkShell { + packages = with pkgs; [ + clang-tools + cmake + gcc15 + gdb + go + ninja + pre-commit + ]; + }; + }; +} diff --git a/testcontainers-bridge/go.mod b/testcontainers-bridge/go.mod index 778b9ac..dae4856 100644 --- a/testcontainers-bridge/go.mod +++ b/testcontainers-bridge/go.mod @@ -1,44 +1,65 @@ module github.com/testcontainers/testcontainers-native -go 1.19 +go 1.25.0 require ( - github.com/docker/go-connections v0.4.0 - github.com/testcontainers/testcontainers-go v0.22.0 + github.com/docker/go-connections v0.6.0 + github.com/testcontainers/testcontainers-go v0.40.0 ) require ( - dario.cat/mergo v1.0.0 // indirect + dario.cat/mergo v1.0.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.0 // indirect - github.com/containerd/containerd v1.7.3 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.5+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v28.5.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/klauspost/compress v1.16.0 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/moby/patternmatcher v0.5.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect + github.com/ebitengine/purego v0.8.4 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.10 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/go-archive v0.1.0 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.4.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect - github.com/opencontainers/runc v1.1.5 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.10.0 // indirect - golang.org/x/tools v0.7.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect - google.golang.org/grpc v1.57.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v4 v4.25.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect + go.opentelemetry.io/otel/metric v1.42.0 // indirect + go.opentelemetry.io/otel/sdk v1.42.0 // indirect + go.opentelemetry.io/otel/trace v1.42.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect + golang.org/x/crypto v0.43.0 // indirect + golang.org/x/sys v0.41.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/testcontainers-bridge/go.sum b/testcontainers-bridge/go.sum index aa11f3f..297acdd 100644 --- a/testcontainers-bridge/go.sum +++ b/testcontainers-bridge/go.sum @@ -1,150 +1,164 @@ -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= -github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= -github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM= +github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= -github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= -github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= +github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= +github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= -github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs= +github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.22.0 h1:hOK4NzNu82VZcKEB1aP9LO1xYssVFMvlfeuDW9JMmV0= -github.com/testcontainers/testcontainers-go v0.22.0/go.mod h1:k0YiPa26xJCRUbUkYqy5rY6NGvSbVCeUBXCvucscBR4= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4= -golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU= +github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho= +go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 h1:THuZiwpQZuHPul65w4WcwEnkX2QIuMT+UFoOrygtoJw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4= +go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI= +go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo= +go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts= +go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY= +go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY= +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= diff --git a/testcontainers-bridge/testcontainers-bridge.go b/testcontainers-bridge/testcontainers-bridge.go index 6acef3f..826c3fe 100644 --- a/testcontainers-bridge/testcontainers-bridge.go +++ b/testcontainers-bridge/testcontainers-bridge.go @@ -121,8 +121,9 @@ func _GetURI(ctx context.Context, container testcontainers.Container, port int) //export tc_bridge_with_wait_for_http func tc_bridge_with_wait_for_http(requestID int, port int, url *C.cchar_t) { - req := func(req *testcontainers.GenericContainerRequest) { + req := func(req *testcontainers.GenericContainerRequest) error { req.WaitingFor = wait.ForHTTP(C.GoString(url)).WithPort(nat.Port(strconv.Itoa(port))) + return nil } registerCustomizer(requestID, req) @@ -130,13 +131,14 @@ func tc_bridge_with_wait_for_http(requestID int, port int, url *C.cchar_t) { //export tc_bridge_with_file func tc_bridge_with_file(requestID int, filePath *C.cchar_t, targetPath *C.cchar_t) { - req := func(req *testcontainers.GenericContainerRequest) { + req := func(req *testcontainers.GenericContainerRequest) error { cfgFile := testcontainers.ContainerFile{ HostFilePath: C.GoString(filePath), ContainerFilePath: C.GoString(targetPath), FileMode: 0755, } req.Files = append(req.Files, cfgFile) + return nil } registerCustomizer(requestID, req) @@ -144,8 +146,9 @@ func tc_bridge_with_file(requestID int, filePath *C.cchar_t, targetPath *C.cchar //export tc_bridge_with_exposed_tcp_port func tc_bridge_with_exposed_tcp_port(requestID int, port int) { - req := func(req *testcontainers.GenericContainerRequest) { + req := func(req *testcontainers.GenericContainerRequest) error { req.ExposedPorts = append(req.ExposedPorts, strconv.Itoa(port)+"/tcp") + return nil } registerCustomizer(requestID, req) diff --git a/testcontainers-c/CMakeLists.txt b/testcontainers-c/CMakeLists.txt index 611e326..1a407c9 100644 --- a/testcontainers-c/CMakeLists.txt +++ b/testcontainers-c/CMakeLists.txt @@ -7,17 +7,30 @@ add_library(${TARGET} SHARED src/container.c ) -target_sources(${TARGET} - PUBLIC FILE_SET HEADERS - BASE_DIRS include - FILES include/testcontainers-c/container.h +target_include_directories(${TARGET} PUBLIC + $ + $ ) target_link_libraries(${TARGET} PRIVATE testcontainers-bridge) -configure_file(cmake.pc.in ${TARGET}.pc @ONLY) -install(FILES ${SHIM_TARGET_LIB} - DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(FILES ${SHIM_TARGET_HEADER} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(FILES ${CMAKE_BINARY_DIR}/${TARGET}.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig) +install(TARGETS ${TARGET} EXPORT ${TARGET}Targets) +install(FILES $ DESTINATION include) + +include(CMakePackageConfigHelpers) +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TARGET}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Config.cmake + INSTALL_DESTINATION lib/cmake/${TARGET} +) + +install(EXPORT ${TARGET}Targets + FILE ${TARGET}Config.cmake + NAMESPACE testcontainers-native:: + DESTINATION lib/cmake/${TARGET} +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Config.cmake + DESTINATION lib/cmake/${TARGET} +) diff --git a/testcontainers-c/cmake.pc.in b/testcontainers-c/cmake.pc.in deleted file mode 100644 index 8c83ec9..0000000 --- a/testcontainers-c/cmake.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ -includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ - -Name: @TARGET_NAME@ -Description: @TARGET_DESCRIPTION@ -Version: @TARGET_VERSION@ - -Requires: -Libs: -L${libdir} -Cflags: -I${includedir} diff --git a/testcontainers-c/cmake/testcontainers-cConfig.cmake.in b/testcontainers-c/cmake/testcontainers-cConfig.cmake.in new file mode 100644 index 0000000..c66a0a1 --- /dev/null +++ b/testcontainers-c/cmake/testcontainers-cConfig.cmake.in @@ -0,0 +1,3 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/testcontainers-cTargets.cmake") diff --git a/testcontainers-cpp/CMakeLists.txt b/testcontainers-cpp/CMakeLists.txt new file mode 100644 index 0000000..ec88660 --- /dev/null +++ b/testcontainers-cpp/CMakeLists.txt @@ -0,0 +1,36 @@ +set(TARGET testcontainers-cpp) +set(TARGET_NAME ${TARGET}) +set(TARGET_DESCRIPTION "Testcontainer library for C++") +set(TARGET_VERSION ${PROJECT_VERSION}) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +add_library(${TARGET} INTERFACE) +target_include_directories(${TARGET} INTERFACE + $ + $ +) + +target_link_libraries(${TARGET} INTERFACE testcontainers-c) + +install(TARGETS ${TARGET} EXPORT ${TARGET}Targets) +install(FILES testcontainers.hpp DESTINATION include) + +include(CMakePackageConfigHelpers) +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TARGET}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Config.cmake + INSTALL_DESTINATION lib/cmake/${TARGET} +) + +install(EXPORT ${TARGET}Targets + FILE ${TARGET}Config.cmake + NAMESPACE testcontainers-native:: + DESTINATION lib/cmake/${TARGET} +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Config.cmake + DESTINATION lib/cmake/${TARGET} +) diff --git a/testcontainers-cpp/cmake/testcontainers-cppConfig.cmake.in b/testcontainers-cpp/cmake/testcontainers-cppConfig.cmake.in new file mode 100644 index 0000000..5358703 --- /dev/null +++ b/testcontainers-cpp/cmake/testcontainers-cppConfig.cmake.in @@ -0,0 +1,3 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/testcontainers-cppTargets.cmake") diff --git a/testcontainers-cpp/testcontainers.hpp b/testcontainers-cpp/testcontainers.hpp new file mode 100644 index 0000000..b73cedb --- /dev/null +++ b/testcontainers-cpp/testcontainers.hpp @@ -0,0 +1,222 @@ +#ifndef TESTCONTAINERS_HPP +#define TESTCONTAINERS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace testcontainers { + +namespace { +extern "C" { +#include "testcontainers-c/container.h" +} +} + +struct TcpPort { + uint16_t underlying; +}; + +enum struct HttpMethod { + Get, + Post, + Head, +}; + +class Builder; + +auto materialize(const auto& in) { +#if __cplusplus >= 202300L + return std::ranges::to(in | std::ranges::views::filter([](char c) { return c != 0x00; })); +#else + auto out = std::string{}; + std::ranges::for_each(in | std::ranges::views::filter([](char c) { return c != 0x00; }), [&](char c) { out += c; }); + return out; +#endif +} + +class Container { +public: + /// A `Container` cannot be explicitly created; use the + /// `Container::Builder` instead. + constexpr Container() = delete; + + /// A `Container` cannot be copied. + explicit constexpr Container(const Container&) = delete; + + /// A `Container` cannot be copied. + constexpr Container& operator=(const Container&) = delete; + + explicit constexpr Container(Container&& other) noexcept : container_id(-1) { *this = std::move(other); } + + constexpr Container& operator=(Container&& other) noexcept { + if (this == &other) { + return *this; + } + + std::swap(container_id, other.container_id); + + return *this; + } + + constexpr ~Container() { + if (container_id != -1) { + tc_container_terminate(container_id); + } + } + + /// Send an HTTP request, type denoted by `method`, to the + /// container. Perform the request on port `port` and to + /// endpoint `endpoint`. + std::pair send_http(HttpMethod method, TcpPort port, const std::filesystem::path& endpoint) { + switch (method) { + case HttpMethod::Get: + return send_http_get(port, endpoint); + case HttpMethod::Post: + return {0, "unimplemented"}; + case HttpMethod::Head: + return {0, "unimplemented"}; + } + + std::unreachable(); + } + +private: + /// The `Configuration` structure holds all expected + /// configuration related to the instantiation of a `Container` + /// instance. + struct Configuration { + using Endpoint = std::filesystem::path; + using Http = std::pair; + using Timeout = std::chrono::milliseconds; + using WaitFor = std::variant; + + int request_id = -1; + WaitFor wait_for_start = std::chrono::milliseconds{1000}; + }; + + /// The `Awaiter` is for different types of waiting. It may be + /// visited (with `std::visit`) when used on e.g. a + /// `Container::Configuration::WaitFor` instance. + struct Awaiter { + explicit constexpr Awaiter(int container_id) : container_id(container_id) {} + + void operator()(const Configuration::Timeout& timeout) { std::this_thread::sleep_for(timeout); } + + void operator()(const Configuration::Http& http) { + const auto& [port, endpoint] = http; + tc_container_with_wait_for_http(container_id, port.underlying, endpoint.c_str()); + } + + private: + int container_id; + }; + + /// Instantiate a container, and optionally wait for it to be + /// ready. + explicit constexpr Container(Configuration configuration) { + char* error = nullptr; + + // Awaiting HTTP-events must occur before the container is + // running. + if (std::holds_alternative(configuration.wait_for_start)) { + Awaiter{container_id}(std::get(configuration.wait_for_start)); + } + + if (container_id = tc_container_run(configuration.request_id, error); container_id == -1) { + throw std::runtime_error{error}; + } + + // Awaiting a timeout must occur after a container is + // running. + if (std::holds_alternative(configuration.wait_for_start)) { + Awaiter{container_id}(std::get(configuration.wait_for_start)); + } + } + + /// Send an HTTP GET request to the container, on port `port` + /// and with endpoint `endpoint`. + constexpr std::pair send_http_get(TcpPort port, const std::filesystem::path& endpoint) const { + static constexpr size_t response_size = 0xFFFF; + static constexpr size_t error_size = 0xFFFF; + auto response_body_raw = std::array{0x00}; + auto error_raw = std::array{0x00}; + + auto code = tc_container_send_http_get(container_id, port.underlying, endpoint.c_str(), + response_body_raw.data(), error_raw.data()); + + if (code == -1) { + auto error = materialize(error_raw); + return std::pair{code, error}; + } + + auto response_body = materialize(response_body_raw); + return std::pair{code, response_body}; + } + + int container_id; + +public: + /// `Builder` is the mechanism to instantiate `Container`s. It + /// serves to configure the setup, and provides an interface to + /// simply check for errors upon container creation. + class Builder { + public: + constexpr Builder(const std::string& image) + : configuration(Container::Configuration{.request_id = tc_container_create(image.c_str())}) {} + + /// Add a file from host `source` to container path + /// `destination`. + Builder with_file(std::filesystem::path source, std::filesystem::path destination) { + tc_container_with_file(configuration.request_id, source.c_str(), destination.c_str()); + return *this; + } + + /// Expose a TCP port out from the container. + Builder expose_port(TcpPort port) { + tc_container_with_exposed_tcp_port(configuration.request_id, port.underlying); + return *this; + } + + /// Add a timeout duration that's waited-for during + /// container startup. + Builder wait_for(std::chrono::milliseconds duration) { + configuration.wait_for_start = duration; + return *this; + } + + /// Add an endpoint to act as health-check, determining if + /// the container is ready for requests. + Builder wait_for_http(TcpPort port, std::filesystem::path endpoint) { + configuration.wait_for_start = std::pair{port, endpoint}; + return *this; + } + + /// Construct a `Container` instance with the configured + /// options. + std::optional build() { + try { + return std::make_optional(Container{configuration}); + } catch (const std::runtime_error& exception) { + return std::nullopt; + } + } + + private: + Configuration configuration; + }; +}; + +} + +#endif // !TESTCONTAINERS_HPP