Skip to content

Commit 5a2a661

Browse files
committed
test: add memory profiler test
1 parent 4a895ba commit 5a2a661

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

bindings/rust/standard/integration/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ bytes = "1.8"
3939
hyper = "1.5"
4040
hyper-util = "0.1"
4141

42+
dhat = "0.3.3"
43+
4244
[build-dependencies]
4345
# The ML-DSA tests require the ML-DSA support added in Openssl-3.5
4446
# Since this overrides the dependency from the openssl-src crate,
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
#[global_allocator]
5+
static ALLOC: dhat::Alloc = dhat::Alloc;
6+
7+
// dhat can only be run in a single thread, so we use a single test case in an
8+
// "integration" test (tests/*) to fulfill those conditions.
9+
10+
use std::task::Poll;
11+
12+
use s2n_tls::error::Error as S2NError;
13+
use s2n_tls::{
14+
security::Policy,
15+
testing::{self, TestPair},
16+
};
17+
18+
/// Return an estimation of the memory size of the IO buffers
19+
///
20+
/// This isn't totally accurate because it doesn't account for any indirection that
21+
/// may be present.
22+
fn test_pair_io_size(pair: &TestPair) -> usize {
23+
pair.io.client_tx_stream.borrow().capacity() + pair.io.server_tx_stream.borrow().capacity()
24+
}
25+
26+
fn fuzzy_equals(actual: usize, expected: usize) -> bool {
27+
const TOLERANCE: usize = 100;
28+
29+
println!("actual: {actual}, expected: {expected}");
30+
actual < expected + TOLERANCE && actual > expected - TOLERANCE
31+
}
32+
33+
/// Note that this does not detect total memory usage, only the memory usage that
34+
/// uses the rust allocator.
35+
///
36+
/// Because the s2n-tls rust bindings set the s2n-tls memory callbacks to use the
37+
/// rust allocator, this does give a good picture of s2n-tls allocations. However
38+
/// this will _not_ report the allocations done by the libcrypto.
39+
///
40+
/// It's important to keep allocations to a minimal amount in this test to give
41+
/// as accurate a picture as possible into s2n-tls memory usage at various stages
42+
/// in the connection lifecycle. We should limit this to
43+
/// - config
44+
/// - client connection
45+
/// - server connection
46+
/// - TestPair io buffers
47+
#[test]
48+
fn memory_consumption() -> Result<(), S2NError> {
49+
const CLIENT_MESSAGE: &[u8] = b"from client";
50+
const SERVER_MESSAGE: &[u8] = b"from server";
51+
52+
let _profiler = dhat::Profiler::new_heap();
53+
let config = testing::build_config(&Policy::from_version("default_tls13")?).unwrap();
54+
55+
let stats = dhat::HeapStats::get();
56+
let config_init = stats.curr_bytes;
57+
58+
let mut pair = TestPair::from_config(&config);
59+
let connection_init = dhat::HeapStats::get().curr_bytes - test_pair_io_size(&pair);
60+
61+
// manually drive the handshake forward to get a measurement while the handshake
62+
// is in flight
63+
assert!(matches!(pair.client.poll_negotiate(), Poll::Pending));
64+
assert!(matches!(pair.server.poll_negotiate(), Poll::Pending));
65+
66+
let handshake_in_progress = dhat::HeapStats::get().curr_bytes - test_pair_io_size(&pair);
67+
68+
pair.handshake()?;
69+
let handshake_complete = dhat::HeapStats::get().curr_bytes - test_pair_io_size(&pair);
70+
71+
let _ = pair.client.poll_send(CLIENT_MESSAGE);
72+
let _ = pair.server.poll_send(SERVER_MESSAGE);
73+
let _ = pair.client.poll_recv(&mut [0; SERVER_MESSAGE.len()]);
74+
let _ = pair.server.poll_recv(&mut [0; CLIENT_MESSAGE.len()]);
75+
let application_data = dhat::HeapStats::get().curr_bytes - test_pair_io_size(&pair);
76+
77+
println!("config: {config_init}");
78+
println!("connection_init: {connection_init}");
79+
println!("handshake in progress: {handshake_in_progress}");
80+
println!("handshake complete: {handshake_complete}");
81+
println!("application data: {application_data}");
82+
83+
assert!(fuzzy_equals(config_init, 5086));
84+
assert!(fuzzy_equals(connection_init, 54440));
85+
assert!(fuzzy_equals(handshake_in_progress, 104911));
86+
assert!(fuzzy_equals(handshake_complete, 70085));
87+
assert!(fuzzy_equals(application_data, 70085));
88+
Ok(())
89+
}

0 commit comments

Comments
 (0)