//! ACME lifecycle (feature `acme`): construct an `Acme` identity with a //! staging URL + tempdir cache; assert spawn-and-return semantics, //! `acme-tls/1` in the ALPN list, and the resolver wiring. No network I/O //! — the directory URL is constructed, never contacted. #![cfg(feature = "acme")] use alktls::{AcmeDirectory, TlsIdentity, TlsServerConfig}; #[tokio::test] async fn acme_spawns_returns_and_appends_acme_tls_alpn() { let dir = tempfile::tempdir().expect("tempdir"); let identity = TlsIdentity::Acme { domains: vec!["localhost".to_string()], cache_dir: dir.path().join("cache"), directory: AcmeDirectory::Custom("http://127.0.0.1:9/directory".to_string()), contact: vec!["mailto:dev@example.com".to_string()], }; let alpn = vec![b"alk/test".to_vec()]; let config = TlsServerConfig::new(&identity, &alpn) .await .expect("ACME config must construct and return immediately (no order awaited)"); let rc = config.rustls_config(); assert_eq!(rc.max_early_data_size, u32::MAX); assert_eq!( rc.alpn_protocols, vec![b"alk/test".to_vec(), b"acme-tls/1".to_vec()], "the crate appends acme-tls/1 on the ACME path only (alknet ADR-027 §7)" ); let cert_resolver = &rc.cert_resolver; let _ = cert_resolver; assert!( !format!("{:?}", cert_resolver).is_empty(), "the ACME resolver is wired as the cert resolver" ); } #[tokio::test] async fn acme_staging_directory_url_is_pinned_in_the_identity() { let identity = TlsIdentity::Acme { domains: vec!["example.com".to_string()], cache_dir: tempfile::tempdir().expect("tempdir").path().join("cache"), directory: AcmeDirectory::Staging, contact: vec!["mailto:dev@example.com".to_string()], }; let alpn = vec![b"alk/test".to_vec()]; let config = TlsServerConfig::new(&identity, &alpn) .await .expect("ACME config must construct with the staging directory URL"); assert_eq!( config.rustls_config().max_early_data_size, u32::MAX, "the ACME branch carries the 0-RTT invariant too" ); }