1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![allow(renamed_and_removed_lints)] #![allow(unknown_lints)] #![warn(missing_docs)]
7#![warn(noop_method_call)]
8#![warn(unreachable_pub)]
9#![warn(clippy::all)]
10#![deny(clippy::await_holding_lock)]
11#![deny(clippy::cargo_common_metadata)]
12#![deny(clippy::cast_lossless)]
13#![deny(clippy::checked_conversions)]
14#![warn(clippy::cognitive_complexity)]
15#![deny(clippy::debug_assert_with_mut_call)]
16#![deny(clippy::exhaustive_enums)]
17#![deny(clippy::exhaustive_structs)]
18#![deny(clippy::expl_impl_clone_on_copy)]
19#![deny(clippy::fallible_impl_from)]
20#![deny(clippy::implicit_clone)]
21#![deny(clippy::large_stack_arrays)]
22#![warn(clippy::manual_ok_or)]
23#![deny(clippy::missing_docs_in_private_items)]
24#![warn(clippy::needless_borrow)]
25#![warn(clippy::needless_pass_by_value)]
26#![warn(clippy::option_option)]
27#![deny(clippy::print_stderr)]
28#![deny(clippy::print_stdout)]
29#![warn(clippy::rc_buffer)]
30#![deny(clippy::ref_option_ref)]
31#![warn(clippy::semicolon_if_nothing_returned)]
32#![warn(clippy::trait_duplication_in_bounds)]
33#![deny(clippy::unchecked_time_subtraction)]
34#![deny(clippy::unnecessary_wraps)]
35#![warn(clippy::unseparated_literal_suffix)]
36#![deny(clippy::unwrap_used)]
37#![deny(clippy::mod_module_files)]
38#![allow(clippy::let_unit_value)] #![allow(clippy::uninlined_format_args)]
40#![allow(clippy::significant_drop_in_scrutinee)] #![allow(clippy::result_large_err)] #![allow(clippy::needless_raw_string_hashes)] #![allow(clippy::needless_lifetimes)] #![allow(mismatched_lifetime_syntaxes)] #![allow(clippy::collapsible_if)] #![deny(clippy::unused_async)]
47#![deny(clippy::string_slice)] #![cfg_attr(not(all(feature = "full")), allow(unused))]
52
53#[cfg(all(
54 any(feature = "native-tls", feature = "rustls"),
55 any(feature = "async-std", feature = "tokio", feature = "smol")
56))]
57pub(crate) mod impls;
58pub mod task;
59
60mod coarse_time;
61mod compound;
62mod dyn_time;
63pub mod general;
64mod network;
65mod opaque;
66pub mod scheduler;
67mod timer;
68mod traits;
69pub mod unimpl;
70pub mod unix;
71
72#[cfg(any(feature = "async-std", feature = "tokio", feature = "smol"))]
73use std::io;
74pub use traits::{
75 Blocking, CertifiedConn, CoarseTimeProvider, NetStreamListener, NetStreamProvider,
76 NoOpStreamOpsHandle, Runtime, SleepProvider, SpawnExt, StreamOps, TlsProvider, ToplevelBlockOn,
77 ToplevelRuntime, UdpProvider, UdpSocket, UnsupportedStreamOp,
78};
79
80pub use coarse_time::{CoarseDuration, CoarseInstant, RealCoarseTimeProvider};
81pub use dyn_time::DynTimeProvider;
82pub use network::{
83 CommonConnectOptions, CommonListenOptions, TcpConnectOptions, TcpListenOptions,
84 UnixConnectOptions, UnixListenOptions,
85};
86pub use timer::{SleepProviderExt, Timeout, TimeoutError};
87
88pub mod tls {
91 #[cfg(all(
92 any(feature = "native-tls", feature = "rustls"),
93 any(feature = "async-std", feature = "tokio", feature = "smol")
94 ))]
95 pub use crate::impls::unimpl_tls::UnimplementedTls;
96 pub use crate::traits::{
97 CertifiedConn, TlsAcceptorSettings, TlsConnector, TlsServerUnsupported,
98 };
99
100 #[cfg(all(
101 feature = "native-tls",
102 any(feature = "tokio", feature = "async-std", feature = "smol")
103 ))]
104 pub use crate::impls::native_tls::NativeTlsProvider;
105 #[cfg(all(
106 feature = "rustls",
107 any(feature = "tokio", feature = "async-std", feature = "smol")
108 ))]
109 pub use crate::impls::rustls::RustlsProvider;
110 #[cfg(all(
111 feature = "rustls",
112 feature = "tls-server",
113 any(feature = "tokio", feature = "async-std", feature = "smol")
114 ))]
115 pub use crate::impls::rustls::rustls_server::{RustlsAcceptor, RustlsServerStream};
116}
117
118#[cfg(all(any(feature = "native-tls", feature = "rustls"), feature = "tokio"))]
119pub mod tokio;
120
121#[cfg(all(any(feature = "native-tls", feature = "rustls"), feature = "async-std"))]
122pub mod async_std;
123
124#[cfg(all(any(feature = "native-tls", feature = "rustls"), feature = "smol"))]
125pub mod smol;
126
127pub use compound::{CompoundRuntime, RuntimeSubstExt};
128
129#[cfg(all(
130 any(feature = "native-tls", feature = "rustls"),
131 feature = "async-std",
132 not(feature = "tokio")
133))]
134use async_std as preferred_backend_mod;
135#[cfg(all(any(feature = "native-tls", feature = "rustls"), feature = "tokio"))]
136use tokio as preferred_backend_mod;
137
138#[cfg(all(
150 any(feature = "native-tls", feature = "rustls"),
151 any(feature = "async-std", feature = "tokio")
152))]
153#[derive(Clone)]
154pub struct PreferredRuntime {
155 inner: preferred_backend_mod::PreferredRuntime,
157}
158
159#[cfg(all(
160 any(feature = "native-tls", feature = "rustls"),
161 any(feature = "async-std", feature = "tokio")
162))]
163crate::opaque::implement_opaque_runtime! {
164 PreferredRuntime { inner : preferred_backend_mod::PreferredRuntime }
165}
166
167#[cfg(all(
168 any(feature = "native-tls", feature = "rustls"),
169 any(feature = "async-std", feature = "tokio")
170))]
171impl PreferredRuntime {
172 pub fn current() -> io::Result<Self> {
208 let rt = preferred_backend_mod::PreferredRuntime::current()?;
209
210 Ok(Self { inner: rt })
211 }
212
213 pub fn create() -> io::Result<Self> {
237 let rt = preferred_backend_mod::PreferredRuntime::create()?;
238
239 Ok(Self { inner: rt })
240 }
241
242 #[doc(hidden)]
252 pub fn run_test<P, F, O>(func: P) -> O
253 where
254 P: FnOnce(Self) -> F,
255 F: futures::Future<Output = O>,
256 {
257 let runtime = Self::create().expect("Failed to create runtime");
258 runtime.clone().block_on(func(runtime))
259 }
260}
261
262#[doc(hidden)]
268pub mod testing__ {
269 pub trait TestOutcome {
272 fn check_ok(&self);
274 }
275 impl TestOutcome for () {
276 fn check_ok(&self) {}
277 }
278 impl<E: std::fmt::Debug> TestOutcome for Result<(), E> {
279 fn check_ok(&self) {
280 self.as_ref().expect("Test failure");
281 }
282 }
283}
284
285macro_rules! declare_conditional_macro {
288 ( $(#[$meta:meta])* macro $name:ident = ($f1:expr, $f2:expr) ) => {
289 $( #[$meta] )*
290 #[cfg(all(feature=$f1, feature=$f2))]
291 #[macro_export]
292 macro_rules! $name {
293 ($tt:tt) => {
294 $tt
295 };
296 }
297
298 $( #[$meta] )*
299 #[cfg(not(all(feature=$f1, feature=$f2)))]
300 #[macro_export]
301 macro_rules! $name {
302 ($tt:tt) => {};
303 }
304
305 pub use $name;
308 };
309}
310
311#[doc(hidden)]
313pub mod cond {
314 declare_conditional_macro! {
315 #[doc(hidden)]
317 macro if_tokio_native_tls_present = ("tokio", "native-tls")
318 }
319 declare_conditional_macro! {
320 #[doc(hidden)]
322 macro if_tokio_rustls_present = ("tokio", "rustls")
323 }
324 declare_conditional_macro! {
325 #[doc(hidden)]
327 macro if_async_std_native_tls_present = ("async-std", "native-tls")
328 }
329 declare_conditional_macro! {
330 #[doc(hidden)]
332 macro if_async_std_rustls_present = ("async-std", "rustls")
333 }
334 declare_conditional_macro! {
335 #[doc(hidden)]
337 macro if_smol_native_tls_present = ("smol", "native-tls")
338 }
339 declare_conditional_macro! {
340 #[doc(hidden)]
342 macro if_smol_rustls_present = ("smol", "rustls")
343 }
344}
345
346#[macro_export]
362#[cfg(all(
363 any(feature = "native-tls", feature = "rustls"),
364 any(feature = "tokio", feature = "async-std", feature = "smol"),
365))]
366macro_rules! test_with_all_runtimes {
367 ( $fn:expr ) => {{
368 use $crate::cond::*;
369 use $crate::testing__::TestOutcome;
370 if_tokio_native_tls_present! {{
375 $crate::tokio::TokioNativeTlsRuntime::run_test($fn).check_ok();
376 }}
377 if_tokio_rustls_present! {{
378 $crate::tokio::TokioRustlsRuntime::run_test($fn).check_ok();
379 }}
380 if_async_std_native_tls_present! {{
381 $crate::async_std::AsyncStdNativeTlsRuntime::run_test($fn).check_ok();
382 }}
383 if_async_std_rustls_present! {{
384 $crate::async_std::AsyncStdRustlsRuntime::run_test($fn).check_ok();
385 }}
386 if_smol_native_tls_present! {{
387 $crate::smol::SmolNativeTlsRuntime::run_test($fn).check_ok();
388 }}
389 if_smol_rustls_present! {{
390 $crate::smol::SmolRustlsRuntime::run_test($fn).check_ok();
391 }}
392 }};
393}
394
395#[macro_export]
407#[cfg(all(
408 any(feature = "native-tls", feature = "rustls"),
409 any(feature = "tokio", feature = "async-std"),
410))]
411macro_rules! test_with_one_runtime {
412 ( $fn:expr ) => {{ $crate::PreferredRuntime::run_test($fn) }};
413}
414
415#[cfg(all(
416 test,
417 any(feature = "native-tls", feature = "rustls"),
418 any(feature = "async-std", feature = "tokio", feature = "smol"),
419 not(miri), ))]
421mod test {
422 #![allow(clippy::bool_assert_comparison)]
424 #![allow(clippy::clone_on_copy)]
425 #![allow(clippy::dbg_macro)]
426 #![allow(clippy::mixed_attributes_style)]
427 #![allow(clippy::print_stderr)]
428 #![allow(clippy::print_stdout)]
429 #![allow(clippy::single_char_pattern)]
430 #![allow(clippy::unwrap_used)]
431 #![allow(clippy::unchecked_time_subtraction)]
432 #![allow(clippy::useless_vec)]
433 #![allow(clippy::needless_pass_by_value)]
434 #![allow(clippy::string_slice)] #![allow(clippy::unnecessary_wraps)]
437 use crate::SleepProviderExt;
438 use crate::ToplevelRuntime;
439
440 use crate::traits::*;
441
442 use futures::io::{AsyncReadExt, AsyncWriteExt};
443 use futures::stream::StreamExt;
444 use native_tls_crate as native_tls;
445 use std::io::Result as IoResult;
446 use std::net::SocketAddr;
447 use std::net::{Ipv4Addr, SocketAddrV4};
448 use web_time_compat::{Duration, Instant, InstantExt, SystemTimeExt};
449
450 fn small_delay<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
453 let rt = runtime.clone();
454 runtime.block_on(async {
455 let i1 = Instant::get();
456 let one_msec = Duration::from_millis(1);
457 rt.sleep(one_msec).await;
458 let i2 = Instant::get();
459 assert!(i2 >= i1 + one_msec);
460 });
461 Ok(())
462 }
463
464 fn small_timeout_ok<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
466 let rt = runtime.clone();
467 runtime.block_on(async {
468 let one_day = Duration::from_secs(86400);
469 let outcome = rt.timeout(one_day, async { 413_u32 }).await;
470 assert_eq!(outcome, Ok(413));
471 });
472 Ok(())
473 }
474
475 fn small_timeout_expire<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
477 use futures::future::pending;
478
479 let rt = runtime.clone();
480 runtime.block_on(async {
481 let one_micros = Duration::from_micros(1);
482 let outcome = rt.timeout(one_micros, pending::<()>()).await;
483 assert_eq!(outcome, Err(crate::TimeoutError));
484 assert_eq!(
485 outcome.err().unwrap().to_string(),
486 "Timeout expired".to_string()
487 );
488 });
489 Ok(())
490 }
491 fn tiny_wallclock<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
496 let rt = runtime.clone();
497 runtime.block_on(async {
498 let i1 = Instant::get();
499 let now = runtime.wallclock();
500 let one_millis = Duration::from_millis(1);
501 let one_millis_later = now + one_millis;
502
503 rt.sleep_until_wallclock(one_millis_later).await;
504
505 let i2 = Instant::get();
506 let newtime = runtime.wallclock();
507 assert!(newtime >= one_millis_later);
508 assert!(i2 - i1 >= one_millis);
509 });
510 Ok(())
511 }
512
513 fn self_connect_tcp<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
517 let localhost = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
518 let rt1 = runtime.clone();
519
520 let listen_options = Default::default();
521 let listener =
522 runtime.block_on(rt1.listen(&(SocketAddr::from(localhost)), &listen_options))?;
523 let addr = listener.local_addr()?;
524
525 runtime.block_on(async {
526 let task1 = async {
527 let mut buf = vec![0_u8; 11];
528 let (mut con, _addr) = listener.incoming().next().await.expect("closed?")?;
529 con.read_exact(&mut buf[..]).await?;
530 IoResult::Ok(buf)
531 };
532 let task2 = async {
533 let connect_options = Default::default();
534 let mut con = rt1.connect(&addr, &connect_options).await?;
535 con.write_all(b"Hello world").await?;
536 con.flush().await?;
537 IoResult::Ok(())
538 };
539
540 let (data, send_r) = futures::join!(task1, task2);
541 send_r?;
542
543 assert_eq!(&data?[..], b"Hello world");
544
545 Ok(())
546 })
547 }
548
549 fn self_connect_udp<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
553 let localhost = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
554 let rt1 = runtime.clone();
555
556 let socket1 = runtime.block_on(rt1.bind(&(localhost.into())))?;
557 let addr1 = socket1.local_addr()?;
558
559 let socket2 = runtime.block_on(rt1.bind(&(localhost.into())))?;
560 let addr2 = socket2.local_addr()?;
561
562 runtime.block_on(async {
563 let task1 = async {
564 let mut buf = [0_u8; 16];
565 let (len, addr) = socket1.recv(&mut buf[..]).await?;
566 IoResult::Ok((buf[..len].to_vec(), addr))
567 };
568 let task2 = async {
569 socket2.send(b"Hello world", &addr1).await?;
570 IoResult::Ok(())
571 };
572
573 let (recv_r, send_r) = futures::join!(task1, task2);
574 send_r?;
575 let (buff, addr) = recv_r?;
576 assert_eq!(addr2, addr);
577 assert_eq!(&buff, b"Hello world");
578
579 Ok(())
580 })
581 }
582
583 fn listener_stream<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
588 let localhost = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
589 let rt1 = runtime.clone();
590
591 let listen_options = Default::default();
592 let listener = runtime
593 .block_on(rt1.listen(&SocketAddr::from(localhost), &listen_options))
594 .unwrap();
595 let addr = listener.local_addr().unwrap();
596 let mut stream = listener.incoming();
597
598 runtime.block_on(async {
599 let task1 = async {
600 let mut n = 0_u32;
601 loop {
602 let (mut con, _addr) = stream.next().await.unwrap()?;
603 let mut buf = [0_u8; 11];
604 con.read_exact(&mut buf[..]).await?;
605 n += 1;
606 if &buf[..] == b"world done!" {
607 break IoResult::Ok(n);
608 }
609 }
610 };
611 let task2 = async {
612 let connect_options = Default::default();
613 for _ in 0_u8..5 {
614 let mut con = rt1.connect(&addr, &connect_options).await?;
615 con.write_all(b"Hello world").await?;
616 con.flush().await?;
617 }
618 let mut con = rt1.connect(&addr, &connect_options).await?;
619 con.write_all(b"world done!").await?;
620 con.flush().await?;
621 con.close().await?;
622 IoResult::Ok(())
623 };
624
625 let (n, send_r) = futures::join!(task1, task2);
626 send_r?;
627
628 assert_eq!(n?, 6);
629
630 Ok(())
631 })
632 }
633
634 fn simple_tls<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
639 static PFX_ID: &[u8] = include_bytes!("test.pfx");
650 static PFX_PASSWORD: &str = "abc";
653
654 let localhost = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
655 let listener = std::net::TcpListener::bind(localhost)?;
656 let addr = listener.local_addr()?;
657
658 let identity = native_tls::Identity::from_pkcs12(PFX_ID, PFX_PASSWORD).unwrap();
659
660 let th = std::thread::spawn(move || {
662 use std::io::{Read, Write};
664 let acceptor = native_tls::TlsAcceptor::new(identity).unwrap();
665 let (con, _addr) = listener.accept()?;
666 let mut con = acceptor.accept(con).unwrap();
667 let mut buf = [0_u8; 16];
668 loop {
669 let n = con.read(&mut buf)?;
670 if n == 0 {
671 break;
672 }
673 con.write_all(&buf[..n])?;
674 }
675 IoResult::Ok(())
676 });
677
678 let connector = runtime.tls_connector();
679
680 runtime.block_on(async {
681 let text = b"I Suddenly Dont Understand Anything";
682 let mut buf = vec![0_u8; text.len()];
683 let connect_options = Default::default();
684 let conn = runtime.connect(&addr, &connect_options).await?;
685 let mut conn = connector.negotiate_unvalidated(conn, "Kan.Aya").await?;
686 assert!(conn.peer_certificate()?.is_some());
687 conn.write_all(text).await?;
688 conn.flush().await?;
689 conn.read_exact(&mut buf[..]).await?;
690 assert_eq!(&buf[..], text);
691 conn.close().await?;
692 IoResult::Ok(())
693 })?;
694
695 th.join().unwrap()?;
696 IoResult::Ok(())
697 }
698
699 fn simple_tls_server<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> {
700 let mut rng = tor_basic_utils::test_rng::testing_rng();
701 let tls_cert = tor_cert_x509::TlsKeyAndCert::create(
702 &mut rng,
703 std::time::SystemTime::get(),
704 "prospit.example.org",
705 "derse.example.org",
706 )
707 .unwrap();
708 let cert = tls_cert.certificates_der()[0].to_vec();
709 let settings = TlsAcceptorSettings::new(tls_cert).unwrap();
710
711 let Ok(tls_acceptor) = runtime.tls_acceptor(settings) else {
712 println!("Skipping tls-server test for runtime {:?}", &runtime);
713 return IoResult::Ok(());
714 };
715 println!("Running tls-server test for runtime {:?}", &runtime);
716
717 let tls_connector = runtime.tls_connector();
718
719 let localhost: SocketAddr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0).into();
720 let rt1 = runtime.clone();
721
722 let msg = b"Derse Reviles Him And Outlaws Frogs Wherever They Can";
723 runtime.block_on(async move {
724 let listen_options = Default::default();
725 let listener = runtime.listen(&localhost, &listen_options).await.unwrap();
726 let address = listener.local_addr().unwrap();
727
728 let h1 = runtime
729 .spawn_with_handle(async move {
730 let conn = listener.incoming().next().await.unwrap().unwrap().0;
731 let mut conn = tls_acceptor.negotiate_unvalidated(conn, "").await.unwrap();
732
733 let mut buf = vec![];
734 conn.read_to_end(&mut buf).await.unwrap();
735 (buf, conn.own_certificate().unwrap().unwrap().into_owned())
736 })
737 .unwrap();
738
739 let h2 = runtime
740 .spawn_with_handle(async move {
741 let connect_options = Default::default();
742 let conn = rt1.connect(&address, &connect_options).await.unwrap();
743 let mut conn = tls_connector
744 .negotiate_unvalidated(conn, "prospit.example.org")
745 .await
746 .unwrap();
747 conn.write_all(msg).await.unwrap();
748 conn.close().await.unwrap();
749 conn.peer_certificate().unwrap().unwrap().into_owned()
750 })
751 .unwrap();
752
753 let (received, server_own_cert) = h1.await;
754 let client_peer_cert = h2.await;
755 assert_eq!(received, msg);
756 assert_eq!(&server_own_cert, &cert);
757 assert_eq!(&client_peer_cert, &cert);
758 });
759 IoResult::Ok(())
760 }
761
762 macro_rules! tests_with_runtime {
763 { $runtime:expr => $($id:ident),* $(,)? } => {
764 $(
765 #[test]
766 fn $id() -> std::io::Result<()> {
767 super::$id($runtime)
768 }
769 )*
770 }
771 }
772
773 macro_rules! runtime_tests {
774 { $($id:ident),* $(,)? } =>
775 {
776 #[cfg(feature="tokio")]
777 mod tokio_runtime_tests {
778 tests_with_runtime! { &crate::tokio::PreferredRuntime::create()? => $($id),* }
779 }
780 #[cfg(feature="async-std")]
781 mod async_std_runtime_tests {
782 tests_with_runtime! { &crate::async_std::PreferredRuntime::create()? => $($id),* }
783 }
784 #[cfg(feature="smol")]
785 mod smol_runtime_tests {
786 tests_with_runtime! { &crate::smol::PreferredRuntime::create()? => $($id),* }
787 }
788 mod default_runtime_tests {
789 tests_with_runtime! { &crate::PreferredRuntime::create()? => $($id),* }
790 }
791 }
792 }
793
794 macro_rules! tls_runtime_tests {
795 { $($id:ident),* $(,)? } =>
796 {
797 #[cfg(all(feature="tokio", feature = "native-tls"))]
798 mod tokio_native_tls_tests {
799 tests_with_runtime! { &crate::tokio::TokioNativeTlsRuntime::create()? => $($id),* }
800 }
801 #[cfg(all(feature="async-std", feature = "native-tls"))]
802 mod async_std_native_tls_tests {
803 tests_with_runtime! { &crate::async_std::AsyncStdNativeTlsRuntime::create()? => $($id),* }
804 }
805 #[cfg(all(feature="smol", feature = "native-tls"))]
806 mod smol_native_tls_tests {
807 tests_with_runtime! { &crate::smol::SmolNativeTlsRuntime::create()? => $($id),* }
808 }
809 #[cfg(all(feature="tokio", feature="rustls"))]
810 mod tokio_rustls_tests {
811 tests_with_runtime! { &crate::tokio::TokioRustlsRuntime::create()? => $($id),* }
812 }
813 #[cfg(all(feature="async-std", feature="rustls"))]
814 mod async_std_rustls_tests {
815 tests_with_runtime! { &crate::async_std::AsyncStdRustlsRuntime::create()? => $($id),* }
816 }
817 #[cfg(all(feature="smol", feature="rustls"))]
818 mod smol_rustls_tests {
819 tests_with_runtime! { &crate::smol::SmolRustlsRuntime::create()? => $($id),* }
820 }
821 mod default_runtime_tls_tests {
822 tests_with_runtime! { &crate::PreferredRuntime::create()? => $($id),* }
823 }
824 }
825 }
826
827 runtime_tests! {
828 small_delay,
829 small_timeout_ok,
830 small_timeout_expire,
831 tiny_wallclock,
832 self_connect_tcp,
833 self_connect_udp,
834 listener_stream,
835 }
836
837 tls_runtime_tests! {
838 simple_tls,
839 simple_tls_server,
840 }
841}