Further improve onion request tests

pull/148/head
gmbnt 6 years ago
parent 0b44f7d7ac
commit 8c6251389d

@ -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<JSON> { internal static func execute(_ verb: Verb, _ url: String, parameters: JSON? = nil, timeout: TimeInterval = HTTP.timeout) -> Promise<JSON> {
return Promise<JSON> { seal in return Promise<JSON> { seal in
let url = URL(string: url)! let url = URL(string: url)!
@ -56,7 +57,7 @@ internal enum HTTP {
let task = urlSession.dataTask(with: request) { data, response, error in let task = urlSession.dataTask(with: request) { data, response, error in
guard let data = data, let response = response as? HTTPURLResponse else { guard let data = data, let response = response as? HTTPURLResponse else {
print("[Loki] \(verb.rawValue) request to \(url) failed.") print("[Loki] \(verb.rawValue) request to \(url) failed.")
return seal.reject(Error.generic) return seal.reject(error ?? Error.generic)
} }
if let error = error { if let error = error {
print("[Loki] \(verb.rawValue) request to \(url) failed due to error: \(error).") print("[Loki] \(verb.rawValue) request to \(url) failed due to error: \(error).")

@ -178,8 +178,8 @@ internal enum OnionRequestAPI {
// MARK: Internal API // MARK: Internal API
/// Sends an onion request to `snode`. Builds new paths as needed. /// 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<Any> { internal static func invoke(_ method: LokiAPITarget.Method, on snode: LokiAPITarget, with parameters: JSON) -> Promise<Data> {
let (promise, seal) = Promise<Any>.pending() let (promise, seal) = Promise<Data>.pending()
workQueue.async { workQueue.async {
let payload: JSON = [ "method" : method.rawValue, "params" : parameters ] let payload: JSON = [ "method" : method.rawValue, "params" : parameters ]
buildOnion(around: payload, targetedAt: snode).done(on: workQueue) { intermediate in buildOnion(around: payload, targetedAt: snode).done(on: workQueue) { intermediate in

@ -1,3 +1,4 @@
import CryptoSwift
import PromiseKit import PromiseKit
@testable import SignalServiceKit @testable import SignalServiceKit
import XCTest import XCTest
@ -8,28 +9,36 @@ class OnionRequestAPITests : XCTestCase {
/// versus the number of failures. /// versus the number of failures.
func testOnionRequestSending() { func testOnionRequestSending() {
let semaphore = DispatchSemaphore(value: 0) let semaphore = DispatchSemaphore(value: 0)
var totalSuccessRate: Double = 0
LokiAPI.getRandomSnode().then(on: OnionRequestAPI.workQueue) { snode -> Promise<LokiAPITarget> in LokiAPI.getRandomSnode().then(on: OnionRequestAPI.workQueue) { snode -> Promise<LokiAPITarget> 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 }.done(on: OnionRequestAPI.workQueue) { snode in
var successCount = 0 var successCount = 0
var failureCount = 0 var failureCount = 0
let promises: [Promise<Void>] = (0..<8).map { _ in let promises: [Promise<Void>] = (0..<10).map { _ in
let mockSessionID = "0582bc30f11e8a9736407adcaca03b049f4acd4af3ae7eb6b6608d30f0b1e6a20e" let mockSessionID = "0582bc30f11e8a9736407adcaca03b049f4acd4af3ae7eb6b6608d30f0b1e6a20e"
let parameters: JSON = [ "pubKey" : mockSessionID ] let parameters: JSON = [ "pubKey" : mockSessionID ]
let (promise, seal) = Promise<Void>.pending() let (promise, seal) = Promise<Void>.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 successCount += 1
print("[Loki] [Onion Request API] Onion request succeeded with result: \(String(data: data, encoding: .utf8)).")
seal.fulfill(()) seal.fulfill(())
}.catch(on: OnionRequestAPI.workQueue) { error in }.catch(on: OnionRequestAPI.workQueue) { error in
failureCount += 1 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) seal.reject(error)
}.finally(on: OnionRequestAPI.workQueue) { }.finally(on: OnionRequestAPI.workQueue) {
let percentage = (successCount == 0) ? 0 : (failureCount == 0) ? 100 : (100 * Double(successCount))/Double(failureCount) let currentSuccessRate = min((100 * Double(successCount))/Double(failureCount), 100)
print("[Loki] [Onion Request API] Succes %: \(percentage).") print("[Loki] [Onion Request API] Current onion request succes rate: \(String(format: "%.1f", currentSuccessRate))%.")
} }
return promise return promise
} }
when(resolved: promises).done(on: OnionRequestAPI.workQueue) { _ in when(resolved: promises).done(on: OnionRequestAPI.workQueue) { _ in
totalSuccessRate = min((100 * Double(successCount))/Double(failureCount), 100)
semaphore.signal() semaphore.signal()
} }
}.catch(on: OnionRequestAPI.workQueue) { error in }.catch(on: OnionRequestAPI.workQueue) { error in
@ -37,7 +46,10 @@ class OnionRequestAPITests : XCTestCase {
semaphore.signal() semaphore.signal()
} }
semaphore.wait() 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 error handling
// TODO: Test race condition handling
} }

Loading…
Cancel
Save