Skip to content

Commit

Permalink
Implement time sensitive tests for FDA check
Browse files Browse the repository at this point in the history
Add test for checking that the newly added timeout to the
FDA check works as expected.
  • Loading branch information
MarkusPettersson98 committed Dec 16, 2024
1 parent e7b3af2 commit 0a8ea83
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 14 deletions.
4 changes: 4 additions & 0 deletions talpid-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,7 @@ features = [

[build-dependencies]
tonic-build = { workspace = true, default-features = false, features = ["transport", "prost"] }


[dev-dependencies]
tokio = { workspace = true, features = [ "io-util", "test-util", "time" ] }
73 changes: 59 additions & 14 deletions talpid-core/src/split_tunnel/macos/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,28 @@ fn check_os_version_support_inner(version: MacosVersion) -> Result<(), Error> {

#[cfg(test)]
mod test {
use super::{check_os_version_support_inner, parse_logger_status, NeedFda, MIN_OS_VERSION};
use super::*;

use std::time::Duration;
use talpid_platform_metadata::MacosVersion;
use tokio::io::{simplex, AsyncWriteExt};

/// A mock-version of std{out,err}. [tokio::io::SimplexStream] implements [AsyncRead], so it can be used to test
/// [parse_logger_status].
fn output(msg: &'static str, lag: Duration) -> impl AsyncRead + Unpin + Send + 'static {
// Ensure that 'msg' contains a newline to prevent user errors
assert!(
msg.contains('\n'),
"Message does not contain a newline!! Make sure to add a newline to '{msg}'"
);
let (stdout_read, mut stdout_write) = simplex(msg.as_bytes().len());
// "print" to "stdout" after `duration`.
tokio::spawn(async move {
tokio::time::sleep(lag).await;
stdout_write.write_all(msg.as_bytes()).await.unwrap();
});
stdout_read
}

#[test]
fn test_min_os_version() {
Expand Down Expand Up @@ -589,10 +609,10 @@ mod test {
);
}

/// If the check times out and 'ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED' is not in stderr, assume
/// full-disk access is available.
/// If process exits without 'ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED', assume full-disk access
/// is available.
#[tokio::test]
async fn test_parse_logger_status_timeout() {
async fn test_parse_logger_status_immediate_exit() {
let need_fda = parse_logger_status(
b"nothing to see here\n".as_slice(),
b"nothing to see here\n".as_slice(),
Expand All @@ -602,24 +622,49 @@ mod test {
assert_eq!(
need_fda,
NeedFda::No,
"expected 'NeedFda::No' when ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED wasn't present"
"expected 'NeedFda::No' on immediate exit",
);
}

/// If process exits without 'ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED', assume full-disk access
/// is available.
/// Check that [parse_logger_status] returns within a reasonable timeframe.
/// "Reasonable" being within [EARLY_FAIL_TIMEOUT].
#[tokio::test(start_paused = true)]
async fn test_parse_logger_status_responsive() {
let start = tokio::time::Instant::now();
let stdout = output("This will never be printed\n", Duration::MAX);
let stderr = output(
"ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED\n",
EARLY_FAIL_TIMEOUT / 2,
);
tokio::time::resume();

let need_fda = parse_logger_status(stdout, stderr).await;

tokio::time::pause();

assert_eq!(
need_fda,
NeedFda::Yes,
"expected 'NeedFda::Yes' when ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED was eventually printed to stderr"
);

// Assert that we did not spend more time waiting than we should
assert!(start.elapsed() < EARLY_FAIL_TIMEOUT);
}

/// Check that [parse_logger_status] doesn't get stuck because nothing is ever output
/// to std{out,err}. It should time out with the assumption that full-disk access is available.
#[tokio::test]
async fn test_parse_logger_status_immediate_exit() {
let need_fda = parse_logger_status(
b"nothing to see here\n".as_slice(),
b"nothing to see here\n".as_slice(),
)
.await;
async fn test_parse_logger_status_timeout() {
let stdout = output("This will never be printed\n", Duration::MAX);
let stderr = output("This will never be printed\n", Duration::MAX);

let need_fda = parse_logger_status(stdout, stderr).await;

assert_eq!(
need_fda,
NeedFda::No,
"expected 'NeedFda::No' on immediate exit",
"expected 'NeedFda::No' when nothing was ever printed to stdout or stderr"
);
}
}

0 comments on commit 0a8ea83

Please sign in to comment.