Files
codex/codex-rs/http-client/src/native_roots_tests.rs
T
jif 80ad49e3b7 Coalesce overlapping native TLS root certificate loads (#54056)
## Why

Concurrent TLS client builds can independently load the same platform trust store. Share overlapping loads while preserving fresh trust reads for later builds.

## What changed

- Share one in-flight native root load without reusing completed loads.
- Bypass sharing when `SSL_CERT_FILE` or `SSL_CERT_DIR` is set, and continue reading custom CA bundles independently for every build.

## Testing

Add tests for overlapping loads, fresh trust after completion, and recovery from a panicking loader. Extend TLS handshake coverage to verify that replacing a custom CA file affects new configurations while existing configurations retain their trust, and that empty or removed files produce errors.

GitOrigin-RevId: 1465ef3faf82f53651d9dbfe314341b17346580b
2026-10-14 17:56:24 +00:00

56 lines
2.1 KiB
Rust

//! Verifies overlapping root loads, fresh trust generations, and panic recovery.
use super::*;
use pretty_assertions::assert_eq;
use rustls_pki_types::CertificateDer;
use rustls_pki_types::pem::PemObject;
use std::sync::mpsc;
use std::thread;
#[test]
fn concurrent_loads_share_roots_but_completed_loads_are_never_reused() {
let loader = NativeRootsLoader::default();
let (entered, started) = mpsc::channel();
let (release, released) = mpsc::channel();
thread::scope(|scope| {
let first_loader = &loader;
let first = scope.spawn(move || {
first_loader.load(|| {
entered.send(()).unwrap();
released.recv().unwrap();
RootCertStore::empty()
})
});
started.recv().unwrap();
let pending = loader.in_flight.lock().unwrap().upgrade().unwrap();
let second = scope.spawn(|| loader.load(|| panic!("overlapping load must be shared")));
// Wait for the second caller to own this generation before allowing it to finish.
while Arc::strong_count(&pending) < 3 {
thread::yield_now();
}
drop(loader.in_flight.lock().unwrap());
release.send(()).unwrap();
let first = first.join().unwrap();
let second = second.join().unwrap();
assert!(Arc::ptr_eq(&first, &second));
// Keep the old generation alive: completion, not refcount expiry, must force a reload.
let updated = loader.load(|| {
let mut roots = RootCertStore::empty();
roots.add_parsable_certificates(
CertificateDer::pem_slice_iter(include_bytes!("../tests/fixtures/test-ca.pem"))
.map(Result::unwrap),
);
roots
});
assert_eq!((first.len(), second.len(), updated.len()), (0, 0, 1));
});
}
#[test]
fn panicking_load_does_not_poison_later_trust_reads() {
let loader = NativeRootsLoader::default();
assert!(std::panic::catch_unwind(|| loader.load(|| panic!("interrupted load"))).is_err());
assert!(loader.load(RootCertStore::empty).is_empty());
}