Skip to content

Commit a708e89

Browse files
committed
test(gateway): cover SNI precedence and atomic reload
1 parent deb2d17 commit a708e89

1 file changed

Lines changed: 73 additions & 0 deletions

File tree

dstack/gateway/src/cert_store.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,4 +517,77 @@ mod tests {
517517
);
518518
assert!(resolver.get().has_cert_for_sni("app.example.com"));
519519
}
520+
521+
#[test]
522+
fn exact_certificate_precedes_parent_wildcard() {
523+
let wildcard = make_test_cert_data();
524+
let exact = make_test_cert_data();
525+
let mut builder = CertStoreBuilder::new();
526+
builder
527+
.add_cert("example.com", &wildcard)
528+
.expect("failed to add wildcard certificate");
529+
builder
530+
.add_exact_cert("api.example.com", &exact)
531+
.expect("failed to add exact certificate");
532+
let store = builder.build();
533+
534+
let exact_selected = store
535+
.resolve_cert("api.example.com")
536+
.expect("exact certificate not selected");
537+
let wildcard_selected = store
538+
.resolve_cert("www.example.com")
539+
.expect("wildcard certificate not selected");
540+
assert!(Arc::ptr_eq(
541+
&exact_selected,
542+
store
543+
.exact_certs
544+
.get("api.example.com")
545+
.expect("exact certificate missing")
546+
));
547+
assert!(Arc::ptr_eq(
548+
&wildcard_selected,
549+
store
550+
.wildcard_certs
551+
.get("example.com")
552+
.expect("wildcard certificate missing")
553+
));
554+
assert!(store.resolve_cert("deep.www.example.com").is_none());
555+
}
556+
557+
#[test]
558+
fn concurrent_reads_never_observe_empty_during_reload() {
559+
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
560+
561+
let resolver = Arc::new(CertResolver::new());
562+
resolver
563+
.update_cert("example.com", &make_test_cert_data())
564+
.expect("failed to install initial certificate");
565+
let finished = Arc::new(AtomicBool::new(false));
566+
let misses = Arc::new(AtomicUsize::new(0));
567+
let readers = (0..4)
568+
.map(|_| {
569+
let resolver = resolver.clone();
570+
let finished = finished.clone();
571+
let misses = misses.clone();
572+
std::thread::spawn(move || {
573+
while !finished.load(Ordering::Acquire) {
574+
if resolver.get().resolve_cert("app.example.com").is_none() {
575+
misses.fetch_add(1, Ordering::Relaxed);
576+
}
577+
}
578+
})
579+
})
580+
.collect::<Vec<_>>();
581+
582+
for _ in 0..20 {
583+
resolver
584+
.update_cert("example.com", &make_test_cert_data())
585+
.expect("hot reload failed");
586+
}
587+
finished.store(true, Ordering::Release);
588+
for reader in readers {
589+
reader.join().expect("reader thread failed");
590+
}
591+
assert_eq!(misses.load(Ordering::Relaxed), 0);
592+
}
520593
}

0 commit comments

Comments
 (0)