summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2023-11-23 16:20:00 +0100
committerMarkus Pettersson <markus.pettersson@mullvad.net>2023-12-06 14:37:18 +0100
commitde860ecc7d9334d3c2d8e95b90caf5c7ca5a2de2 (patch)
tree6968512dec750fe8acacb9854f1c5c2332106d2b
parent1b930b893fa3fcb06f5fee4affbfb62887d0e68a (diff)
downloadmullvadvpn-de860ecc7d9334d3c2d8e95b90caf5c7ca5a2de2.tar.xz
mullvadvpn-de860ecc7d9334d3c2d8e95b90caf5c7ca5a2de2.zip
Add `test_connecting_state_when_corrupted_state_cache`
Add regression test which checks that the daemon successfully recovers from a corrupt target state cache. If the target state cache is corrupt, the daemon will default to the `Connecting` target state on startup.
-rw-r--r--test/test-manager/src/tests/tunnel_state.rs50
-rw-r--r--test/test-rpc/src/client.rs13
-rw-r--r--test/test-rpc/src/lib.rs2
3 files changed, 53 insertions, 12 deletions
diff --git a/test/test-manager/src/tests/tunnel_state.rs b/test/test-manager/src/tests/tunnel_state.rs
index 176127d7c5..90a5086863 100644
--- a/test/test-manager/src/tests/tunnel_state.rs
+++ b/test/test-manager/src/tests/tunnel_state.rs
@@ -353,15 +353,51 @@ pub async fn test_connecting_state_when_corrupted_state_cache(
// Stopping the app should write to the state target cache.
log::info!("Stopping the app");
- rpc.restart_app().await?;
+ rpc.stop_app().await?;
+
+ // Intentionally corrupt the state cache. Note that we can not simply remove
+ // the cache, as this will put the app in the default target state which is
+ // 'unsecured'.
+ log::info!("Figuring out where state cache resides on test runner ..");
+ let state_cache = rpc
+ .find_mullvad_app_cache_dir()
+ .await?
+ .join("target-start-state.json");
+ log::info!(
+ "Intentionally writing garbage to the state cache {file}",
+ file = state_cache.display()
+ );
+ rpc.write_file(state_cache, "cookie was here".into())
+ .await?;
- // Intentionally corrupt the state cache
- todo!("Intentionally corrupt the state cache");
- // Start a leak monitor
- todo!("Start a leak monitor");
// Start the app & make sure that we start in the 'connecting state'. The
// side-effect of this is that no network traffic is allowed to leak.
- todo!("Start the app");
- assert_tunnel_state!(&mut mullvad_client, TunnelState::Connecting { .. });
+ log::info!("Starting the app back up again");
+ rpc.start_app().await?;
+
+ let new_state = wait_for_tunnel_state(mullvad_client.clone(), |state| {
+ matches!(
+ state,
+ TunnelState::Connecting { .. } | TunnelState::Connected { .. } | TunnelState::Error(..)
+ )
+ })
+ .await
+ .map_err(|err| {
+ log::error!("App did not start in an expected state.");
+ err
+ })?;
+
+ assert!(
+ matches!(
+ new_state,
+ TunnelState::Connecting { .. } | TunnelState::Connected { .. }
+ ),
+ "App is not in either `Connecting` or `Connected` state after starting with corrupt state cache! There is a possibility of leaks during app startup"
+ );
+
+ log::info!(
+ "App started successfully! It successfully recovered from a corrupt tunnel state cache."
+ );
+
Ok(())
}
diff --git a/test/test-rpc/src/client.rs b/test/test-rpc/src/client.rs
index acc462dd60..6234db0262 100644
--- a/test/test-rpc/src/client.rs
+++ b/test/test-rpc/src/client.rs
@@ -1,5 +1,6 @@
use std::{
collections::HashMap,
+ path::Path,
time::{Duration, SystemTime},
};
@@ -51,7 +52,7 @@ impl ServiceClient {
self.client.uninstall_app(ctx, env).await?
}
- /// Execute a program.
+ /// Execute a program with additional environment-variables set.
pub async fn exec_env<
I: IntoIterator<Item = T>,
M: IntoIterator<Item = (K, T)>,
@@ -282,14 +283,18 @@ impl ServiceClient {
.await?
}
- pub async fn write_file(&self, dest: String, bytes: Vec<u8>) -> Result<(), Error> {
+ pub async fn write_file(&self, dest: impl AsRef<Path>, bytes: Vec<u8>) -> Result<(), Error> {
log::debug!(
"Writing {bytes} bytes to \"{file}\"",
bytes = bytes.len(),
- file = dest
+ file = dest.as_ref().display()
);
self.client
- .write_file(tarpc::context::current(), dest, bytes)
+ .write_file(
+ tarpc::context::current(),
+ dest.as_ref().to_path_buf(),
+ bytes,
+ )
.await?
}
diff --git a/test/test-rpc/src/lib.rs b/test/test-rpc/src/lib.rs
index 65ccb2fb7a..2e5007a808 100644
--- a/test/test-rpc/src/lib.rs
+++ b/test/test-rpc/src/lib.rs
@@ -173,7 +173,7 @@ mod service {
async fn copy_file(src: String, dest: String) -> Result<(), Error>;
/// Write arbitrary bytes to some file `dest` on the test runner.
- async fn write_file(dest: String, bytes: Vec<u8>) -> Result<(), Error>;
+ async fn write_file(dest: PathBuf, bytes: Vec<u8>) -> Result<(), Error>;
async fn reboot() -> Result<(), Error>;