diff options
| author | David Lönnhager <david.l@mullvad.net> | 2025-10-20 10:21:58 +0200 |
|---|---|---|
| committer | Joakim Hulthe <joakim.hulthe@mullvad.net> | 2025-10-23 10:22:48 +0200 |
| commit | 1145cd7fbd798921aca80c76f8877251532e2c71 (patch) | |
| tree | 7e5145e97a43e7d1431c4b0832f98fcd9043d088 | |
| parent | 82920c6f3702bc41028519dba318e39bd44cc52a (diff) | |
| parent | 846369cb9301e524b19af38e07091367c27ef6e4 (diff) | |
| download | mullvadvpn-1145cd7fbd798921aca80c76f8877251532e2c71.tar.xz mullvadvpn-1145cd7fbd798921aca80c76f8877251532e2c71.zip | |
Merge branch 'fix-check-interruption' into prepare-2025.13
| -rw-r--r-- | mullvad-daemon/src/version/router.rs | 118 |
1 files changed, 114 insertions, 4 deletions
diff --git a/mullvad-daemon/src/version/router.rs b/mullvad-daemon/src/version/router.rs index 7f878a94bc..d38edcca2e 100644 --- a/mullvad-daemon/src/version/router.rs +++ b/mullvad-daemon/src/version/router.rs @@ -351,14 +351,66 @@ where } } #[cfg(in_app_upgrade)] - State::Downloaded { .. } | State::Downloading { .. } => { + State::Downloading { + version_cache: prev_cache, + .. + } => { + let prev_app_version_info = + to_app_version_info(prev_cache, self.beta_program, None); let app_version_info = to_app_version_info(&version_cache, self.beta_program, None); - log::warn!("Received new version while upgrading: {app_version_info:?}"); - AppVersionInfoEvent { + let event = AppVersionInfoEvent { + is_new: prev_app_version_info != app_version_info, app_version_info, - is_new: true, + }; + + if !event.is_new { + log::trace!("Ignoring same version in downloading state"); + // Return here to avoid resetting the state to `HasVersion` + // We update the cache because ignored information (eg available beta if beta + // program is off) may have changed + *prev_cache = version_cache.clone(); + return event; } + + log::warn!("Received new version while downloading. Aborting download"); + + event + } + #[cfg(in_app_upgrade)] + State::Downloaded { + version_cache: prev_cache, + verified_installer_path, + .. + } => { + let prev_app_version_info = to_app_version_info( + prev_cache, + self.beta_program, + Some(verified_installer_path.clone()), + ); + let app_version_info = to_app_version_info( + &version_cache, + self.beta_program, + Some(verified_installer_path.clone()), + ); + + let event = AppVersionInfoEvent { + is_new: prev_app_version_info != app_version_info, + app_version_info, + }; + + if !event.is_new { + log::trace!("Ignoring same version in downloaded state"); + // Return here to avoid resetting the state to `HasVersion` + // We update the cache because ignored information (eg available beta if beta + // program is off) may have changed + *prev_cache = version_cache.clone(); + return event; + } + + log::warn!("Received new version in downloaded state. Aborting download"); + + event } }; self.state = State::HasVersion { version_cache }; @@ -1114,6 +1166,64 @@ mod test { } #[tokio::test] + async fn test_update_in_downloaded_state() { + let (mut version_router, _channels) = make_version_router::<SuccessfulAppDownloader>(); + let mut version_cache_test = get_new_stable_version_cache(); + + version_router.on_new_version(version_cache_test.clone()); + + // Start upgrading + version_router.update_application(); + // Check that the state is now downloading + assert!(matches!(version_router.state, State::Downloading { .. }),); + + // Should remain in downloading state if same version is received + version_router.on_new_version(version_cache_test.clone()); + assert!( + matches!(version_router.state, State::Downloading { .. }), + "state should be Downloading, was {:?}", + version_router.state, + ); + + // Unless the version is different + version_cache_test.version_info.stable.version.incremental += 1; + version_router.on_new_version(version_cache_test.clone()); + assert!( + matches!(version_router.state, State::HasVersion { .. }), + "state should be HasVersion, was {:?}", + version_router.state, + ); + + // Restart upgrade + version_router.update_application(); + + // Drive the download to completion + assert_eq!(version_router.run_step().await, ControlFlow::Continue(())); + assert!( + matches!(version_router.state, State::Downloaded { .. }), + "state should be Downloaded, was {:?}", + version_router.state, + ); + + // Should remain in downloaded state if same version is received + version_router.on_new_version(version_cache_test.clone()); + assert!( + matches!(version_router.state, State::Downloaded { .. }), + "state should be Downloaded, was {:?}", + version_router.state, + ); + + // Unless the version is different + version_cache_test.version_info.stable.version.incremental += 1; + version_router.on_new_version(version_cache_test.clone()); + assert!( + matches!(version_router.state, State::HasVersion { .. }), + "state should be HasVersion, was {:?}", + version_router.state, + ); + } + + #[tokio::test] async fn test_failed_verification() { let (mut version_router, _channels) = make_version_router::<FailingAppVerifier>(); let version_cache_test = get_new_stable_version_cache(); |
