summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPNTests/MullvadSettings/MigrationManagerMultiProcessUpgradeTests.swift
blob: 42574c89adb78cdeb3a16588ec03a9d1589be075 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//
//  MigrationManagerMultiProcessUpgradeTests.swift
//  MullvadVPNTests
//
//  Created by Marco Nikic on 2024-10-03.
//  Copyright © 2025 Mullvad VPN AB. All rights reserved.
//

import XCTest

@testable import MullvadMockData
@testable import MullvadREST
@testable import MullvadSettings
@testable import MullvadTypes

extension MigrationManagerTests {
    func testMigrationDoesNothingIfAnotherProcessIsRunningUpdates() throws {
        let hostProcess = DispatchQueue(label: "net.tests.HostMigration")
        let packetTunnelProcess = DispatchQueue(label: "net.tests.PacketTunnelMigration")
        let osakaRelayConstraints = RelayConstraints(
            exitLocations: .only(UserSelectedRelays(locations: [.city("jp", "osa")]))
        )
        var settingsV1 = TunnelSettingsV1()
        settingsV1.relayConstraints = osakaRelayConstraints

        try write(settings: settingsV1, version: SchemaVersion.v1.rawValue, in: Self.store)

        let backgroundMigrationExpectation = expectation(description: "Migration from packet tunnel")
        let foregroundMigrationExpectation = expectation(description: "Migration from host")
        nonisolated(unsafe) var migrationHappenedInPacketTunnel = false
        nonisolated(unsafe) var migrationHappenedInHost = false

        packetTunnelProcess.async { [unowned self] in
            manager.migrateSettings(store: MigrationManagerTests.store) { backgroundMigrationResult in
                if case .success = backgroundMigrationResult {
                    migrationHappenedInPacketTunnel = true
                }
                backgroundMigrationExpectation.fulfill()
            }
        }

        hostProcess.async { [unowned self] in
            manager.migrateSettings(store: MigrationManagerTests.store) { foregroundMigrationResult in
                if case .success = foregroundMigrationResult {
                    migrationHappenedInHost = true
                }
                foregroundMigrationExpectation.fulfill()
            }
        }

        wait(for: [backgroundMigrationExpectation, foregroundMigrationExpectation], timeout: .UnitTest.timeout)

        // Migration happens either in one process, or the other.
        // This check guarantees it didn't happen in both simultaneously.
        XCTAssertNotEqual(migrationHappenedInPacketTunnel, migrationHappenedInHost)
        let latestSettings = try SettingsManager.readSettings()
        XCTAssertEqual(osakaRelayConstraints, latestSettings.relayConstraints)
    }
}