From 8c6251389d40e9d790828cb58853a36b398281c6 Mon Sep 17 00:00:00 2001 From: gmbnt Date: Fri, 3 Apr 2020 10:34:05 +1100 Subject: [PATCH] Further improve onion request tests --- SignalServiceKit/src/Loki/API/HTTP/HTTP.swift | 3 ++- .../API/Onion Requests/OnionRequestAPI.swift | 4 ++-- .../Onion Requests/OnionRequestAPITests.swift | 22 ++++++++++++++----- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/SignalServiceKit/src/Loki/API/HTTP/HTTP.swift b/SignalServiceKit/src/Loki/API/HTTP/HTTP.swift index d9a5c4e0e..47126029e 100644 --- a/SignalServiceKit/src/Loki/API/HTTP/HTTP.swift +++ b/SignalServiceKit/src/Loki/API/HTTP/HTTP.swift @@ -39,6 +39,7 @@ internal enum HTTP { } } + // MARK: Main internal static func execute(_ verb: Verb, _ url: String, parameters: JSON? = nil, timeout: TimeInterval = HTTP.timeout) -> Promise { return Promise { seal in let url = URL(string: url)! @@ -56,7 +57,7 @@ internal enum HTTP { let task = urlSession.dataTask(with: request) { data, response, error in guard let data = data, let response = response as? HTTPURLResponse else { print("[Loki] \(verb.rawValue) request to \(url) failed.") - return seal.reject(Error.generic) + return seal.reject(error ?? Error.generic) } if let error = error { print("[Loki] \(verb.rawValue) request to \(url) failed due to error: \(error).") diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift index a9b718c9b..9a238f5fb 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift @@ -178,8 +178,8 @@ internal enum OnionRequestAPI { // MARK: Internal API /// Sends an onion request to `snode`. Builds new paths as needed. - internal static func invoke(_ method: LokiAPITarget.Method, on snode: LokiAPITarget, with parameters: JSON) -> Promise { - let (promise, seal) = Promise.pending() + internal static func invoke(_ method: LokiAPITarget.Method, on snode: LokiAPITarget, with parameters: JSON) -> Promise { + let (promise, seal) = Promise.pending() workQueue.async { let payload: JSON = [ "method" : method.rawValue, "params" : parameters ] buildOnion(around: payload, targetedAt: snode).done(on: workQueue) { intermediate in diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPITests.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPITests.swift index 150749423..1c4fb43b1 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPITests.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPITests.swift @@ -1,3 +1,4 @@ +import CryptoSwift import PromiseKit @testable import SignalServiceKit import XCTest @@ -8,28 +9,36 @@ class OnionRequestAPITests : XCTestCase { /// versus the number of failures. func testOnionRequestSending() { let semaphore = DispatchSemaphore(value: 0) + var totalSuccessRate: Double = 0 LokiAPI.getRandomSnode().then(on: OnionRequestAPI.workQueue) { snode -> Promise in - return OnionRequestAPI.getPath(excluding: snode).map(on: OnionRequestAPI.workQueue) { _ in snode } + return OnionRequestAPI.getPath(excluding: snode).map(on: OnionRequestAPI.workQueue) { _ in snode } // Ensure we only build a path once }.done(on: OnionRequestAPI.workQueue) { snode in var successCount = 0 var failureCount = 0 - let promises: [Promise] = (0..<8).map { _ in + let promises: [Promise] = (0..<10).map { _ in let mockSessionID = "0582bc30f11e8a9736407adcaca03b049f4acd4af3ae7eb6b6608d30f0b1e6a20e" let parameters: JSON = [ "pubKey" : mockSessionID ] let (promise, seal) = Promise.pending() - OnionRequestAPI.invoke(.getSwarm, on: snode, with: parameters).done(on: OnionRequestAPI.workQueue) { _ in + OnionRequestAPI.invoke(.getSwarm, on: snode, with: parameters).done(on: OnionRequestAPI.workQueue) { data in successCount += 1 + print("[Loki] [Onion Request API] Onion request succeeded with result: \(String(data: data, encoding: .utf8)).") seal.fulfill(()) }.catch(on: OnionRequestAPI.workQueue) { error in failureCount += 1 + if case GCM.Error.fail = error { + print("[Loki] [Onion Request API] Onion request failed due a decryption error.") + } else { + print("[Loki] [Onion Request API] Onion request failed due to error: \(error).") + } seal.reject(error) }.finally(on: OnionRequestAPI.workQueue) { - let percentage = (successCount == 0) ? 0 : (failureCount == 0) ? 100 : (100 * Double(successCount))/Double(failureCount) - print("[Loki] [Onion Request API] Succes %: \(percentage).") + let currentSuccessRate = min((100 * Double(successCount))/Double(failureCount), 100) + print("[Loki] [Onion Request API] Current onion request succes rate: \(String(format: "%.1f", currentSuccessRate))%.") } return promise } when(resolved: promises).done(on: OnionRequestAPI.workQueue) { _ in + totalSuccessRate = min((100 * Double(successCount))/Double(failureCount), 100) semaphore.signal() } }.catch(on: OnionRequestAPI.workQueue) { error in @@ -37,7 +46,10 @@ class OnionRequestAPITests : XCTestCase { semaphore.signal() } semaphore.wait() + print("[Loki] [Onion Request API] Total onion request succes rate: \(String(format: "%.1f", totalSuccessRate))%.") + XCTAssert(totalSuccessRate >= 90) } // TODO: Test error handling + // TODO: Test race condition handling }