summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPNTests/MullvadVPN/GeneralAPIs/OutgoingConnectionProxyTests.swift
blob: 401a0bc6a0e94649871e09d3fd296e6641dfdd29 (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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//
//  OutgoingConnectionProxyTests.swift
//  MullvadVPNTests
//
//  Created by Mojgan on 2023-10-25.
//  Copyright © 2025 Mullvad VPN AB. All rights reserved.
//

import XCTest

@testable import MullvadMockData

final class OutgoingConnectionProxyTests: XCTestCase {
    private var mockIPV6ConnectionData: Data!
    private var mockIPV4ConnectionData: Data!
    private let hostname = "mullvad.net"

    private let encoder = JSONEncoder()

    override func setUpWithError() throws {
        mockIPV4ConnectionData = try encoder.encode(IPV4ConnectionData.mock)
        mockIPV6ConnectionData = try encoder.encode(IPV6ConnectionData.mock)
    }

    override func tearDownWithError() throws {
        mockIPV4ConnectionData.removeAll()
        mockIPV6ConnectionData.removeAll()
    }

    func testSuccessGettingIPV4() async throws {
        let iPv4Expectation = expectation(description: "Did receive IPv4")

        let outgoingConnectionProxy = OutgoingConnectionProxy(
            urlSession: URLSessionStub(
                response: (mockIPV4ConnectionData, createHTTPURLResponse(ip: .v4, statusCode: 200))
            ), hostname: hostname)

        let result = try await outgoingConnectionProxy.getIPV4(retryStrategy: .noRetry)

        if result.ip == IPV4ConnectionData.mock.ip {
            iPv4Expectation.fulfill()
        }
        await fulfillment(of: [iPv4Expectation], timeout: .UnitTest.timeout)
    }

    func testFailureGettingIPV4() async throws {
        let noIPv4Expectation = expectation(description: "Did not receive IPv4")

        let outgoingConnectionProxy = OutgoingConnectionProxy(
            urlSession: URLSessionStub(
                response: (Data(), createHTTPURLResponse(ip: .v4, statusCode: 503))
            ), hostname: hostname)

        await XCTAssertThrowsErrorAsync(try await outgoingConnectionProxy.getIPV4(retryStrategy: .noRetry)) { _ in
            noIPv4Expectation.fulfill()
        }
        await fulfillment(of: [noIPv4Expectation], timeout: .UnitTest.timeout)
    }

    func testSuccessGettingIPV6() async throws {
        let ipv6Expectation = expectation(description: "Did receive IPv6")

        let outgoingConnectionProxy = OutgoingConnectionProxy(
            urlSession: URLSessionStub(
                response: (mockIPV6ConnectionData, createHTTPURLResponse(ip: .v6, statusCode: 200))
            ), hostname: hostname)

        let result = try await outgoingConnectionProxy.getIPV6(retryStrategy: .noRetry)

        if result.ip == IPV6ConnectionData.mock.ip {
            ipv6Expectation.fulfill()
        }
        await fulfillment(of: [ipv6Expectation], timeout: .UnitTest.timeout)
    }

    func testFailureGettingIPV6() async throws {
        let noIPv6Expectation = expectation(description: "Did not receive IPv6")

        let outgoingConnectionProxy = OutgoingConnectionProxy(
            urlSession: URLSessionStub(
                response: (mockIPV6ConnectionData, createHTTPURLResponse(ip: .v6, statusCode: 404))
            ), hostname: hostname)

        await XCTAssertThrowsErrorAsync(try await outgoingConnectionProxy.getIPV6(retryStrategy: .noRetry)) { _ in
            noIPv6Expectation.fulfill()
        }
        await fulfillment(of: [noIPv6Expectation], timeout: .UnitTest.timeout)
    }
}

extension OutgoingConnectionProxyTests {
    private func createHTTPURLResponse(ip: OutgoingConnectionProxy.ExitIPVersion, statusCode: Int) -> HTTPURLResponse {
        return HTTPURLResponse(
            url: URL(string: "https://\(ip.host(hostname: hostname))/json")!,
            statusCode: statusCode,
            httpVersion: nil,
            headerFields: ["Content-Type": "application/json"]
        )!
    }
}