From 9b117d965594be00f392c140968366c41e291372 Mon Sep 17 00:00:00 2001 From: David Cook Date: Tue, 30 Apr 2024 17:57:36 -0500 Subject: [PATCH] Upgrade testcontainers to 0.16 (#3073) --- Cargo.lock | 317 +++++++++++++++++---- Cargo.toml | 24 +- aggregator_core/src/datastore/test_util.rs | 48 +--- core/src/test_util/testcontainers.rs | 23 +- integration_tests/src/client.rs | 37 ++- integration_tests/src/daphne.rs | 23 +- integration_tests/src/janus.rs | 31 +- integration_tests/tests/common/mod.rs | 2 +- integration_tests/tests/daphne.rs | 15 +- integration_tests/tests/divviup_ts.rs | 26 +- integration_tests/tests/janus.rs | 49 +--- interop_binaries/src/lib.rs | 16 +- interop_binaries/tests/end_to_end.rs | 61 ++-- 13 files changed, 401 insertions(+), 271 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4a4ad7de..e6e53be03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -247,7 +247,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -258,7 +258,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -439,13 +439,53 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bollard" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aed08d3adb6ebe0eff737115056652670ae290f177759aac19c30456135f94c" +dependencies = [ + "base64 0.22.0", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "home", + "http 1.1.0", + "http-body-util", + "hyper 1.3.1", + "hyper-named-pipe", + "hyper-rustls 0.26.0", + "hyper-util", + "hyperlocal-next", + "log", + "pin-project-lite", + "rustls 0.22.4", + "rustls-native-certs 0.7.0", + "rustls-pemfile 2.1.1", + "rustls-pki-types", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "tower-service", + "url", + "winapi", +] + [[package]] name = "bollard-stubs" -version = "1.42.0-rc.3" +version = "1.44.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed59b5c00048f48d7af971b71f800fdf23e858844a6f9e4d32ca72e9399e7864" +checksum = "709d9aa1c37abb89d40f19f5d0ad6f0d88cb1581264e571c9350fc5bb89cf1c5" dependencies = [ "serde", + "serde_repr", "serde_with", ] @@ -570,7 +610,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -823,9 +863,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.4" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ "darling_core", "darling_macro", @@ -833,27 +873,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.4" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.10.0", - "syn 1.0.109", + "syn 2.0.60", ] [[package]] name = "darling_macro" -version = "0.13.4" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 1.0.109", + "syn 2.0.60", ] [[package]] @@ -943,6 +983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -977,6 +1018,38 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "docker_credential" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31951f49556e34d90ed28342e1df7e1cb7a229c4cab0aecc627b5d91edd41d07" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -1311,7 +1384,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -1406,7 +1479,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -1740,6 +1813,21 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-named-pipe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" +dependencies = [ + "hex", + "hyper 1.3.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", + "winapi", +] + [[package]] name = "hyper-rustls" version = "0.24.1" @@ -1751,7 +1839,7 @@ dependencies = [ "hyper 0.14.27", "log", "rustls 0.21.11", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", ] @@ -1766,7 +1854,9 @@ dependencies = [ "http 1.1.0", "hyper 1.3.1", "hyper-util", + "log", "rustls 0.22.4", + "rustls-native-certs 0.7.0", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -1805,6 +1895,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "hyperlocal-next" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf569d43fa9848e510358c07b80f4adf34084ddc28c6a4a651ee8474c070dcc" +dependencies = [ + "hex", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "iana-time-zone" version = "0.1.57" @@ -1852,6 +1957,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -1862,6 +1968,7 @@ checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -2452,6 +2559,16 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.4.1", + "libc", +] + [[package]] name = "libsqlite3-sys" version = "0.27.0" @@ -2677,7 +2794,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -2794,6 +2911,12 @@ dependencies = [ "tokio-stream", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-float" version = "2.10.0" @@ -2866,6 +2989,31 @@ dependencies = [ "windows-targets 0.48.1", ] +[[package]] +name = "parse-display" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06af5f9333eb47bd9ba8462d612e37a8328a5cb80b13f0af4de4c3b89f52dee5" +dependencies = [ + "parse-display-derive", + "regex", + "regex-syntax 0.8.2", +] + +[[package]] +name = "parse-display-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc9252f259500ee570c75adcc4e317fa6f57a1e47747d622e0bf838002a7b790" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "regex-syntax 0.8.2", + "structmeta", + "syn 2.0.60", +] + [[package]] name = "paste" version = "1.0.14" @@ -2928,7 +3076,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -2977,7 +3125,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -3060,7 +3208,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -3169,9 +3317,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.74" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -3211,7 +3359,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -3333,6 +3481,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.4" @@ -3535,7 +3694,7 @@ dependencies = [ "quote", "rand", "rustc_version", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -3604,6 +3763,19 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.1", + "rustls-pki-types", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.3" @@ -3775,7 +3947,7 @@ checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -3799,6 +3971,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "serde_spanned" version = "0.6.5" @@ -3831,24 +4014,32 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ + "base64 0.22.0", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.1", "serde", + "serde_derive", + "serde_json", "serde_with_macros", + "time", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" dependencies = [ "darling", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.60", ] [[package]] @@ -4328,6 +4519,29 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +[[package]] +name = "structmeta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" +dependencies = [ + "proc-macro2", + "quote", + "structmeta-derive", + "syn 2.0.60", +] + +[[package]] +name = "structmeta-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "subtle" version = "2.5.0" @@ -4347,9 +4561,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.46" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -4382,19 +4596,24 @@ dependencies = [ [[package]] name = "testcontainers" -version = "0.15.0" +version = "0.16.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d2931d7f521af5bae989f716c3fa43a6af9af7ec7a5e21b59ae40878cec00" +checksum = "279c6fb2b8db23b09ce3a68ec5dd720530e5743af060a65be8ab9acfb7394aef" dependencies = [ + "async-trait", + "bollard", "bollard-stubs", + "dirs", + "docker_credential", "futures", - "hex", - "hmac", "log", - "rand", + "parse-display", "serde", "serde_json", - "sha2", + "serde_with", + "tokio", + "tokio-util", + "url", ] [[package]] @@ -4414,7 +4633,7 @@ checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -4509,7 +4728,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -4584,9 +4803,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -4760,7 +4979,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -4936,7 +5155,7 @@ checksum = "916054381183f0cfed7604bf7de2044a760624a50d26eef5492468fb73083bbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -4947,7 +5166,7 @@ checksum = "916e37646d33632b88ca02d4b8c4e2e6376f2a89d9888de71b7d82c150ed1f6c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -5274,7 +5493,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -5308,7 +5527,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5599,7 +5818,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] @@ -5619,7 +5838,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.60", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 75c73805d..89139aca5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,17 +1,5 @@ [workspace] -members = [ - "aggregator", - "aggregator_api", - "aggregator_core", - "build_script_utils", - "client", - "collector", - "core", - "integration_tests", - "interop_binaries", - "messages", - "tools", -] +members = ["aggregator", "aggregator_api", "aggregator_core", "build_script_utils", "client", "collector", "core", "integration_tests", "interop_binaries", "messages", "tools"] resolver = "2" [workspace.package] @@ -42,7 +30,7 @@ janus_core = { version = "0.5", path = "core" } janus_integration_tests = { version = "0.5", path = "integration_tests" } janus_interop_binaries = { version = "0.5", path = "interop_binaries" } janus_messages = { version = "0.5", path = "messages" } -k8s-openapi = { version = "0.20.0", features = ["v1_24"] } # keep this version in sync with what is referenced by the indirect dependency via `kube` +k8s-openapi = { version = "0.20.0", features = ["v1_24"] } # keep this version in sync with what is referenced by the indirect dependency via `kube` kube = { version = "0.87.2", default-features = false, features = ["client", "rustls-tls"] } opentelemetry = { version = "0.22", features = ["metrics"] } opentelemetry_sdk = { version = "0.22", features = ["metrics"] } @@ -53,7 +41,7 @@ serde_test = "1.0.175" serde_yaml = "0.9.34" reqwest = { version = "0.12.4", default-features = false, features = ["rustls-tls"] } rstest = "0.17.0" -testcontainers = "0.15.0" +testcontainers = "0.16.5" thiserror = "1.0" tokio = { version = "1.37", features = ["full", "tracing"] } trillium = "0.2.19" @@ -75,6 +63,6 @@ debug = 0 # relatively fast compilation. It is intended for use in size-constrained testing scenarios, e.g. # building a binary artifact that ends up embedded in another binary. inherits = "dev" -opt-level = "z" # Optimize for size. -debug = false # Do not generate debug info. -strip = true # Strip symbols from binary. +opt-level = "z" # Optimize for size. +debug = false # Do not generate debug info. +strip = true # Strip symbols from binary. diff --git a/aggregator_core/src/datastore/test_util.rs b/aggregator_core/src/datastore/test_util.rs index 5af2fcaff..d520cc8fa 100644 --- a/aggregator_core/src/datastore/test_util.rs +++ b/aggregator_core/src/datastore/test_util.rs @@ -14,20 +14,18 @@ use sqlx::{ use std::{ path::PathBuf, str::FromStr, - sync::{Arc, Barrier, Weak}, - thread::{self, JoinHandle}, + sync::{Arc, Weak}, }; -use testcontainers::RunnableImage; -use tokio::sync::{oneshot, Mutex}; +use testcontainers::{runners::AsyncRunner, ContainerAsync, RunnableImage}; +use tokio::sync::Mutex; use tokio_postgres::{connect, Config, NoTls}; use tracing::trace; use super::SUPPORTED_SCHEMA_VERSIONS; struct EphemeralDatabase { + _db_container: ContainerAsync, port_number: u16, - shutdown_barrier: Arc, - join_handle: Option>, } impl EphemeralDatabase { @@ -49,30 +47,15 @@ impl EphemeralDatabase { } async fn start() -> Self { - let (port_tx, port_rx) = oneshot::channel(); - let shutdown_barrier = Arc::new(Barrier::new(2)); - let join_handle = thread::spawn({ - let shutdown_barrier = Arc::clone(&shutdown_barrier); - move || { - // Start an instance of Postgres running in a container. - let container_client = testcontainers::clients::Cli::default(); - let db_container = container_client.run(RunnableImage::from(Postgres::default())); - const POSTGRES_DEFAULT_PORT: u16 = 5432; - let port_number = db_container.get_host_port_ipv4(POSTGRES_DEFAULT_PORT); - trace!("Postgres container is up with port {port_number}"); - port_tx.send(port_number).unwrap(); - - // Wait for the barrier as a shutdown signal. - shutdown_barrier.wait(); - trace!("Shutting down Postgres container with port {port_number}"); - } - }); - let port_number = port_rx.await.unwrap(); + // Start an instance of Postgres running in a container. + let db_container = RunnableImage::from(Postgres::default()).start().await; + const POSTGRES_DEFAULT_PORT: u16 = 5432; + let port_number = db_container.get_host_port_ipv4(POSTGRES_DEFAULT_PORT).await; + trace!("Postgres container is up with port {port_number}"); Self { + _db_container: db_container, port_number, - shutdown_barrier, - join_handle: Some(join_handle), } } @@ -84,17 +67,6 @@ impl EphemeralDatabase { } } -impl Drop for EphemeralDatabase { - fn drop(&mut self) { - // Wait on the shutdown barrier, which will cause the container-management thread to - // begin shutdown. Then wait for the container-management thread itself to terminate. - // This guarantees container shutdown finishes before dropping the EphemeralDatabase - // completes. - self.shutdown_barrier.wait(); - self.join_handle.take().unwrap().join().unwrap(); - } -} - /// EphemeralDatastore represents an ephemeral datastore instance. It has methods allowing /// creation of Datastores, as well as the ability to retrieve the underlying connection pool. /// diff --git a/core/src/test_util/testcontainers.rs b/core/src/test_util/testcontainers.rs index ad3898a22..e19bb16bf 100644 --- a/core/src/test_util/testcontainers.rs +++ b/core/src/test_util/testcontainers.rs @@ -1,26 +1,7 @@ //! Testing functionality that interacts with the testcontainers library. -use std::{ - collections::HashMap, - sync::{Arc, Mutex, Weak}, -}; -use testcontainers::{clients::Cli, core::WaitFor, Image}; - -/// Returns a container client, possibly shared with other callers to this function. -pub fn container_client() -> Arc { - // Once `Weak::new` is const in stable Rust, this should be replaced by a static variable - // initialized to `Mutex::new(Weak::new())`. [https://github.com/rust-lang/rust/issues/95091] - lazy_static::lazy_static! { - static ref CONTAINER_CLIENT_MU: Mutex> = Mutex::new(Weak::new()); - } - - let mut container_client = CONTAINER_CLIENT_MU.lock().unwrap(); - container_client.upgrade().unwrap_or_else(|| { - let client = Arc::new(Cli::default()); - *container_client = Arc::downgrade(&client); - client - }) -} +use std::collections::HashMap; +use testcontainers::{core::WaitFor, Image}; /// A [`testcontainers::Image`] that provides a Postgres server. #[derive(Debug)] diff --git a/integration_tests/src/client.rs b/integration_tests/src/client.rs index 6b5fb45bd..d7b949b90 100644 --- a/integration_tests/src/client.rs +++ b/integration_tests/src/client.rs @@ -15,7 +15,7 @@ use prio::{ use rand::random; use serde_json::{json, Value}; use std::env; -use testcontainers::{clients::Cli, core::WaitFor, Image, RunnableImage}; +use testcontainers::{core::WaitFor, runners::AsyncRunner, Image, RunnableImage}; use url::Url; /// Extension trait to encode measurements for VDAFs as JSON objects, according to @@ -149,7 +149,6 @@ pub enum ClientBackend<'a> { /// Uploads reports by starting a containerized client implementation, and sending it requests /// using draft-dcook-ppm-dap-interop-test-design. Container { - container_client: &'a Cli, container_image: InteropClient, network: &'a str, }, @@ -161,7 +160,7 @@ impl<'a> ClientBackend<'a> { task_parameters: &TaskParameters, (leader_port, helper_port): (u16, u16), vdaf: V, - ) -> anyhow::Result> + ) -> anyhow::Result> where V: vdaf::Client<16> + InteropClientEncoding, { @@ -174,25 +173,24 @@ impl<'a> ClientBackend<'a> { .await .map_err(Into::into), ClientBackend::Container { - container_client, container_image, network, } => Ok(ClientImplementation::new_container( - container_client, container_image.clone(), network, task_parameters, vdaf, - )), + ) + .await), } } } -pub struct ContainerClientImplementation<'d, V> +pub struct ContainerClientImplementation where V: vdaf::Client<16>, { - _container: ContainerLogsDropGuard<'d, InteropClient>, + _container: ContainerLogsDropGuard, leader: Url, helper: Url, task_id: TaskId, @@ -205,15 +203,15 @@ where /// A DAP client implementation, specialized to work with a particular VDAF. See also /// [`ClientBackend`]. -pub enum ClientImplementation<'d, V> +pub enum ClientImplementation where V: vdaf::Client<16>, { InProcess { client: Client }, - Container(Box>), + Container(Box>), } -impl<'d, V> ClientImplementation<'d, V> +impl ClientImplementation where V: vdaf::Client<16> + InteropClientEncoding, { @@ -221,7 +219,7 @@ where task_parameters: &TaskParameters, (leader_port, helper_port): (u16, u16), vdaf: V, - ) -> Result, janus_client::Error> { + ) -> Result, janus_client::Error> { let aggregator_endpoints = task_parameters .endpoint_fragments .port_forwarded_endpoints(leader_port, helper_port); @@ -256,8 +254,7 @@ where Ok(ClientImplementation::InProcess { client }) } - pub fn new_container( - container_client: &'d Cli, + pub async fn new_container( container_image: InteropClient, network: &str, task_parameters: &TaskParameters, @@ -265,13 +262,13 @@ where ) -> Self { let random_part = hex::encode(random::<[u8; 4]>()); let client_container_name = format!("client-{random_part}"); - let container = container_client.run( - RunnableImage::from(container_image) - .with_network(network) - .with_container_name(client_container_name), - ); + let container = RunnableImage::from(container_image) + .with_network(network) + .with_container_name(client_container_name) + .start() + .await; let container = ContainerLogsDropGuard::new(container); - let host_port = container.get_host_port_ipv4(8080); + let host_port = container.get_host_port_ipv4(8080).await; let http_client = reqwest::Client::new(); let aggregator_endpoints = task_parameters .endpoint_fragments diff --git a/integration_tests/src/daphne.rs b/integration_tests/src/daphne.rs index 5a804a020..1a4eaf44b 100644 --- a/integration_tests/src/daphne.rs +++ b/integration_tests/src/daphne.rs @@ -10,22 +10,23 @@ use std::{ process::{Command, Stdio}, thread::panicking, }; -use testcontainers::{clients::Cli, Container, GenericImage, RunnableImage}; +use testcontainers::{runners::AsyncRunner, ContainerAsync, GenericImage, RunnableImage}; const DAPHNE_HELPER_IMAGE_NAME_AND_TAG: &str = "cloudflare/daphne-worker-helper:sha-f6b3ef1"; /// Represents a running Daphne test instance. -pub struct Daphne<'a> { - daphne_container: Container<'a, GenericImage>, +pub struct Daphne { + daphne_container: ContainerAsync, role: Role, + port: u16, } -impl<'a> Daphne<'a> { +impl Daphne { const INTERNAL_SERVING_PORT: u16 = 8080; /// Create and start a new hermetic Daphne test instance in the given Docker network, configured /// to service the given task. The aggregator port is also exposed to the host. - pub async fn new(container_client: &'a Cli, network: &str, task: &Task) -> Daphne<'a> { + pub async fn new(network: &str, task: &Task) -> Daphne { let image_name_and_tag = match task.role() { Role::Leader => panic!("A leader container image for Daphne is not yet available"), Role::Helper => DAPHNE_HELPER_IMAGE_NAME_AND_TAG, @@ -38,8 +39,10 @@ impl<'a> Daphne<'a> { let runnable_image = RunnableImage::from(GenericImage::new(image_name, image_tag)) .with_network(network) .with_container_name(endpoint.host_str().unwrap()); - let daphne_container = container_client.run(runnable_image); - let port = daphne_container.get_host_port_ipv4(Self::INTERNAL_SERVING_PORT); + let daphne_container = runnable_image.start().await; + let port = daphne_container + .get_host_port_ipv4(Self::INTERNAL_SERVING_PORT) + .await; // Wait for Daphne container to begin listening on the port. await_http_server(port).await; @@ -61,17 +64,17 @@ impl<'a> Daphne<'a> { Self { daphne_container, role, + port, } } /// Returns the port of the aggregator on the host. pub fn port(&self) -> u16 { - self.daphne_container - .get_host_port_ipv4(Self::INTERNAL_SERVING_PORT) + self.port } } -impl<'a> Drop for Daphne<'a> { +impl Drop for Daphne { fn drop(&mut self) { // We assume that if a Daphne value is dropped during a panic, we are in the middle of // test failure. In this case, export logs if logs_path() suggests doing so. diff --git a/integration_tests/src/janus.rs b/integration_tests/src/janus.rs index 92c9ae6f9..fdb3b2b40 100644 --- a/integration_tests/src/janus.rs +++ b/integration_tests/src/janus.rs @@ -10,26 +10,29 @@ use std::{ process::{Command, Stdio}, thread::panicking, }; -use testcontainers::{clients::Cli, Container, RunnableImage}; +use testcontainers::{runners::AsyncRunner, ContainerAsync, RunnableImage}; /// Represents a running Janus test instance in a container. -pub struct Janus<'a> { +pub struct Janus { role: Role, - container: Container<'a, Aggregator>, + container: ContainerAsync, + port: u16, } -impl<'a> Janus<'a> { +impl Janus { /// Create and start a new hermetic Janus test instance in the given Docker network, configured /// to service the given task. The aggregator port is also exposed to the host. - pub async fn new(container_client: &'a Cli, network: &str, task: &Task) -> Janus<'a> { + pub async fn new(network: &str, task: &Task) -> Janus { // Start the Janus interop aggregator container running. let endpoint = task.aggregator_url(task.role()).unwrap(); - let container = container_client.run( - RunnableImage::from(Aggregator::default()) - .with_network(network) - .with_container_name(endpoint.host_str().unwrap()), - ); - let port = container.get_host_port_ipv4(Aggregator::INTERNAL_SERVING_PORT); + let container = RunnableImage::from(Aggregator::default()) + .with_network(network) + .with_container_name(endpoint.host_str().unwrap()) + .start() + .await; + let port = container + .get_host_port_ipv4(Aggregator::INTERNAL_SERVING_PORT) + .await; // Wait for the container to start listening on its port. await_http_server(port).await; @@ -40,17 +43,17 @@ impl<'a> Janus<'a> { Self { role: *task.role(), container, + port, } } /// Returns the port of the aggregator on the host. pub fn port(&self) -> u16 { - self.container - .get_host_port_ipv4(Aggregator::INTERNAL_SERVING_PORT) + self.port } } -impl<'a> Drop for Janus<'a> { +impl Drop for Janus { fn drop(&mut self) { // We assume that if a Janus value is dropped during a panic, we are in the middle of // test failure. In this case, export logs if log_export_path() suggests doing so. diff --git a/integration_tests/tests/common/mod.rs b/integration_tests/tests/common/mod.rs index 3542bef9e..89d97c922 100644 --- a/integration_tests/tests/common/mod.rs +++ b/integration_tests/tests/common/mod.rs @@ -116,7 +116,7 @@ pub async fn submit_measurements_and_verify_aggregate_generic( leader_port: u16, vdaf: V, test_case: &AggregationTestCase, - client_implementation: &ClientImplementation<'_, V>, + client_implementation: &ClientImplementation, ) where V: vdaf::Client<16> + vdaf::Collector + InteropClientEncoding, V::AggregateResult: PartialEq, diff --git a/integration_tests/tests/daphne.rs b/integration_tests/tests/daphne.rs index e351e6070..6f4ad2a9b 100644 --- a/integration_tests/tests/daphne.rs +++ b/integration_tests/tests/daphne.rs @@ -1,9 +1,6 @@ use common::{submit_measurements_and_verify_aggregate, test_task_builders}; use janus_aggregator_core::task::{QueryType, Task}; -use janus_core::{ - task::VdafInstance, - test_util::{install_test_trace_subscriber, testcontainers::container_client}, -}; +use janus_core::{task::VdafInstance, test_util::install_test_trace_subscriber}; use janus_integration_tests::{client::ClientBackend, daphne::Daphne, janus::Janus}; use janus_interop_binaries::test_util::generate_network_name; use janus_messages::Role; @@ -34,9 +31,8 @@ async fn daphne_janus() { .try_into() .unwrap(); - let container_client = container_client(); - let leader = Daphne::new(&container_client, &network, &leader_task).await; - let helper = Janus::new(&container_client, &network, &helper_task).await; + let leader = Daphne::new(&network, &leader_task).await; + let helper = Janus::new(&network, &helper_task).await; // Run the behavioral test. submit_measurements_and_verify_aggregate( @@ -70,9 +66,8 @@ async fn janus_daphne() { .try_into() .unwrap(); - let container_client = container_client(); - let leader = Janus::new(&container_client, &network, &leader_task).await; - let helper = Daphne::new(&container_client, &network, &helper_task).await; + let leader = Janus::new(&network, &leader_task).await; + let helper = Daphne::new(&network, &helper_task).await; // Run the behavioral test. submit_measurements_and_verify_aggregate( diff --git a/integration_tests/tests/divviup_ts.rs b/integration_tests/tests/divviup_ts.rs index 3aecb6648..f4464999e 100644 --- a/integration_tests/tests/divviup_ts.rs +++ b/integration_tests/tests/divviup_ts.rs @@ -2,28 +2,23 @@ use common::{submit_measurements_and_verify_aggregate, test_task_builders}; use janus_aggregator_core::task::QueryType; -use janus_core::{ - task::VdafInstance, - test_util::{install_test_trace_subscriber, testcontainers::container_client}, -}; +use janus_core::{task::VdafInstance, test_util::install_test_trace_subscriber}; use janus_integration_tests::{ client::{ClientBackend, InteropClient}, janus::Janus, }; use janus_interop_binaries::test_util::generate_network_name; -use testcontainers::clients::Cli; mod common; -async fn run_divviup_ts_integration_test(container_client: &Cli, vdaf: VdafInstance) { +async fn run_divviup_ts_integration_test(vdaf: VdafInstance) { let (task_parameters, leader_task, helper_task) = test_task_builders(vdaf, QueryType::TimeInterval); let network = generate_network_name(); - let leader = Janus::new(container_client, &network, &leader_task.build()).await; - let helper = Janus::new(container_client, &network, &helper_task.build()).await; + let leader = Janus::new(&network, &leader_task.build()).await; + let helper = Janus::new(&network, &helper_task.build()).await; let client_backend = ClientBackend::Container { - container_client, container_image: InteropClient::divviup_ts(), network: &network, }; @@ -39,26 +34,23 @@ async fn run_divviup_ts_integration_test(container_client: &Cli, vdaf: VdafInsta async fn janus_divviup_ts_count() { install_test_trace_subscriber(); - run_divviup_ts_integration_test(&container_client(), VdafInstance::Prio3Count).await; + run_divviup_ts_integration_test(VdafInstance::Prio3Count).await; } #[tokio::test(flavor = "multi_thread")] async fn janus_divviup_ts_sum() { install_test_trace_subscriber(); - run_divviup_ts_integration_test(&container_client(), VdafInstance::Prio3Sum { bits: 8 }).await; + run_divviup_ts_integration_test(VdafInstance::Prio3Sum { bits: 8 }).await; } #[tokio::test(flavor = "multi_thread")] async fn janus_divviup_ts_histogram() { install_test_trace_subscriber(); - run_divviup_ts_integration_test( - &container_client(), - VdafInstance::Prio3Histogram { - buckets: Vec::from([1, 10, 100, 1000]), - }, - ) + run_divviup_ts_integration_test(VdafInstance::Prio3Histogram { + buckets: Vec::from([1, 10, 100, 1000]), + }) .await; } diff --git a/integration_tests/tests/janus.rs b/integration_tests/tests/janus.rs index a7af9113d..bde9b2dcb 100644 --- a/integration_tests/tests/janus.rs +++ b/integration_tests/tests/janus.rs @@ -1,40 +1,32 @@ use common::{submit_measurements_and_verify_aggregate, test_task_builders}; use janus_aggregator_core::task::QueryType; -use janus_core::{ - task::VdafInstance, - test_util::{install_test_trace_subscriber, testcontainers::container_client}, -}; +use janus_core::{task::VdafInstance, test_util::install_test_trace_subscriber}; use janus_integration_tests::{client::ClientBackend, janus::Janus, TaskParameters}; use janus_interop_binaries::test_util::generate_network_name; -use testcontainers::clients::Cli; mod common; /// A pair of Janus instances, running in containers, against which integration tests may be run. -struct JanusPair<'a> { +struct JanusPair { /// Task parameters needed by the client and collector, for the task configured in both Janus /// aggregators. task_parameters: TaskParameters, /// Handle to the leader's resources, which are released on drop. - leader: Janus<'a>, + leader: Janus, /// Handle to the helper's resources, which are released on drop. - helper: Janus<'a>, + helper: Janus, } -impl<'a> JanusPair<'a> { +impl JanusPair { /// Set up a new pair of containerized Janus test instances, and set up a new task in each using /// the given VDAF and query type. - pub async fn new( - container_client: &'a Cli, - vdaf: VdafInstance, - query_type: QueryType, - ) -> JanusPair<'a> { + pub async fn new(vdaf: VdafInstance, query_type: QueryType) -> JanusPair { let (task_parameters, leader_task, helper_task) = test_task_builders(vdaf, query_type); let network = generate_network_name(); - let leader = Janus::new(container_client, &network, &leader_task.build()).await; - let helper = Janus::new(container_client, &network, &helper_task.build()).await; + let leader = Janus::new(&network, &leader_task.build()).await; + let helper = Janus::new(&network, &helper_task.build()).await; Self { task_parameters, @@ -50,13 +42,7 @@ async fn janus_janus_count() { install_test_trace_subscriber(); // Start servers. - let container_client = container_client(); - let janus_pair = JanusPair::new( - &container_client, - VdafInstance::Prio3Count, - QueryType::TimeInterval, - ) - .await; + let janus_pair = JanusPair::new(VdafInstance::Prio3Count, QueryType::TimeInterval).await; // Run the behavioral test. submit_measurements_and_verify_aggregate( @@ -73,13 +59,8 @@ async fn janus_janus_sum_16() { install_test_trace_subscriber(); // Start servers. - let container_client = container_client(); - let janus_pair = JanusPair::new( - &container_client, - VdafInstance::Prio3Sum { bits: 16 }, - QueryType::TimeInterval, - ) - .await; + let janus_pair = + JanusPair::new(VdafInstance::Prio3Sum { bits: 16 }, QueryType::TimeInterval).await; // Run the behavioral test. submit_measurements_and_verify_aggregate( @@ -98,9 +79,7 @@ async fn janus_janus_histogram_4_buckets() { let buckets = Vec::from([3, 6, 8]); // Start servers. - let container_client = container_client(); let janus_pair = JanusPair::new( - &container_client, VdafInstance::Prio3Histogram { buckets }, QueryType::TimeInterval, ) @@ -121,9 +100,7 @@ async fn janus_janus_count_vec_15() { install_test_trace_subscriber(); // Start servers. - let container_client = container_client(); let janus_pair = JanusPair::new( - &container_client, VdafInstance::Prio3CountVec { length: 15 }, QueryType::TimeInterval, ) @@ -144,9 +121,7 @@ async fn janus_janus_fixed_size() { install_test_trace_subscriber(); // Start servers. - let container_client = container_client(); let janus_pair = JanusPair::new( - &container_client, VdafInstance::Prio3Count, QueryType::FixedSize { max_batch_size: 50, @@ -169,9 +144,7 @@ async fn janus_janus_fixed_size() { async fn janus_janus_sum_vec() { install_test_trace_subscriber(); - let container_client = container_client(); let janus_pair = JanusPair::new( - &container_client, VdafInstance::Prio3SumVec { bits: 16, length: 15, diff --git a/interop_binaries/src/lib.rs b/interop_binaries/src/lib.rs index 58cd6556d..59c00f55a 100644 --- a/interop_binaries/src/lib.rs +++ b/interop_binaries/src/lib.rs @@ -26,7 +26,7 @@ use std::{ sync::Arc, thread::panicking, }; -use testcontainers::{Container, Image}; +use testcontainers::{ContainerAsync, Image}; use tokio::sync::Mutex; use tracing_log::LogTracer; use tracing_subscriber::{prelude::*, EnvFilter, Registry}; @@ -392,17 +392,17 @@ struct ContainerInspectEntry { name: String, } -pub struct ContainerLogsDropGuard<'d, I: Image> { - container: Container<'d, I>, +pub struct ContainerLogsDropGuard { + container: ContainerAsync, } -impl<'d, I: Image> ContainerLogsDropGuard<'d, I> { - pub fn new(container: Container) -> ContainerLogsDropGuard { +impl ContainerLogsDropGuard { + pub fn new(container: ContainerAsync) -> ContainerLogsDropGuard { ContainerLogsDropGuard { container } } } -impl<'d, I: Image> Drop for ContainerLogsDropGuard<'d, I> { +impl Drop for ContainerLogsDropGuard { fn drop(&mut self) { if !panicking() { return; @@ -442,8 +442,8 @@ impl<'d, I: Image> Drop for ContainerLogsDropGuard<'d, I> { } } -impl<'d, I: Image> Deref for ContainerLogsDropGuard<'d, I> { - type Target = Container<'d, I>; +impl Deref for ContainerLogsDropGuard { + type Target = ContainerAsync; fn deref(&self) -> &Self::Target { &self.container diff --git a/interop_binaries/tests/end_to_end.rs b/interop_binaries/tests/end_to_end.rs index 50cbf21fe..3d7471fa4 100644 --- a/interop_binaries/tests/end_to_end.rs +++ b/interop_binaries/tests/end_to_end.rs @@ -3,7 +3,7 @@ use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; use futures::future::join_all; use janus_core::{ task::PRIO3_VERIFY_KEY_LENGTH, - test_util::{install_test_trace_subscriber, testcontainers::container_client}, + test_util::install_test_trace_subscriber, time::{Clock, RealClock, TimeExt}, }; use janus_interop_binaries::{ @@ -20,7 +20,7 @@ use rand::random; use reqwest::{header::CONTENT_TYPE, StatusCode, Url}; use serde_json::{json, Value}; use std::time::Duration as StdDuration; -use testcontainers::RunnableImage; +use testcontainers::{runners::AsyncRunner, RunnableImage}; use tokio::time::sleep; #[cfg(feature = "fpvec_bounded_l2")] @@ -57,46 +57,53 @@ async fn run( }; // Create and start containers. - let container_client = container_client(); let network = generate_network_name(); let client_container = ContainerLogsDropGuard::new( - container_client.run( - RunnableImage::from(Client::default()) - .with_network(&network) - .with_container_name(generate_unique_name("client")), - ), + RunnableImage::from(Client::default()) + .with_network(&network) + .with_container_name(generate_unique_name("client")) + .start() + .await, ); - let client_port = client_container.get_host_port_ipv4(Client::INTERNAL_SERVING_PORT); + let client_port = client_container + .get_host_port_ipv4(Client::INTERNAL_SERVING_PORT) + .await; let leader_name = generate_unique_name("leader"); let leader_container = ContainerLogsDropGuard::new( - container_client.run( - RunnableImage::from(Aggregator::default()) - .with_network(&network) - .with_container_name(leader_name.clone()), - ), + RunnableImage::from(Aggregator::default()) + .with_network(&network) + .with_container_name(leader_name.clone()) + .start() + .await, ); - let leader_port = leader_container.get_host_port_ipv4(Aggregator::INTERNAL_SERVING_PORT); + let leader_port = leader_container + .get_host_port_ipv4(Aggregator::INTERNAL_SERVING_PORT) + .await; let helper_name = generate_unique_name("helper"); let helper_container = ContainerLogsDropGuard::new( - container_client.run( - RunnableImage::from(Aggregator::default()) - .with_network(&network) - .with_container_name(helper_name.clone()), - ), + RunnableImage::from(Aggregator::default()) + .with_network(&network) + .with_container_name(helper_name.clone()) + .start() + .await, ); - let helper_port = helper_container.get_host_port_ipv4(Aggregator::INTERNAL_SERVING_PORT); + let helper_port = helper_container + .get_host_port_ipv4(Aggregator::INTERNAL_SERVING_PORT) + .await; let collector_container = ContainerLogsDropGuard::new( - container_client.run( - RunnableImage::from(Collector::default()) - .with_network(&network) - .with_container_name(generate_unique_name("collector")), - ), + RunnableImage::from(Collector::default()) + .with_network(&network) + .with_container_name(generate_unique_name("collector")) + .start() + .await, ); - let collector_port = collector_container.get_host_port_ipv4(Collector::INTERNAL_SERVING_PORT); + let collector_port = collector_container + .get_host_port_ipv4(Collector::INTERNAL_SERVING_PORT) + .await; // Wait for all containers to sucessfully respond to HTTP requests. join_all(