mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
14 KiB
Swift
315 lines
14 KiB
Swift
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import Foundation
|
|
|
|
import Quick
|
|
import Nimble
|
|
|
|
@testable import SessionUtilitiesKit
|
|
|
|
class BencodeSpec: QuickSpec {
|
|
struct TestType: Codable, Equatable {
|
|
let intValue: Int
|
|
let stringValue: String
|
|
}
|
|
|
|
struct TestType2: Codable, Equatable {
|
|
let stringValue: String
|
|
let boolValue: Bool
|
|
}
|
|
|
|
struct TestType3: Codable, Equatable {
|
|
let stringValue: String
|
|
let boolValue: Bool
|
|
|
|
init(_ stringValue: String, _ boolValue: Bool) {
|
|
self.stringValue = stringValue
|
|
self.boolValue = boolValue
|
|
}
|
|
|
|
init(from decoder: Decoder) throws {
|
|
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
self = TestType3(
|
|
try container.decode(String.self, forKey: .stringValue),
|
|
((try? container.decode(Bool.self, forKey: .boolValue)) ?? false)
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - Spec
|
|
|
|
override func spec() {
|
|
describe("Bencode") {
|
|
// MARK: - when decoding
|
|
context("when decoding") {
|
|
// MARK: -- should decode a basic string
|
|
it("should decode a basic string") {
|
|
let basicStringData: Data = "5:howdy".data(using: .utf8)!
|
|
let result = try? Bencode.decode(String.self, from: basicStringData)
|
|
|
|
expect(result).to(equal("howdy"))
|
|
}
|
|
|
|
// MARK: -- should decode a basic integer
|
|
it("should decode a basic integer") {
|
|
let basicIntegerData: Data = "i3e".data(using: .utf8)!
|
|
let result = try? Bencode.decode(Int.self, from: basicIntegerData)
|
|
|
|
expect(result).to(equal(3))
|
|
}
|
|
|
|
// MARK: -- should decode a list of integers
|
|
it("should decode a list of integers") {
|
|
let basicIntListData: Data = "li1ei2ee".data(using: .utf8)!
|
|
let result = try? Bencode.decode([Int].self, from: basicIntListData)
|
|
|
|
expect(result).to(equal([1, 2]))
|
|
}
|
|
|
|
// MARK: -- should decode a basic dict
|
|
it("should decode a basic dict") {
|
|
let basicDictData: Data = "d4:spaml1:a1:bee".data(using: .utf8)!
|
|
let result = try? Bencode.decode([String: [String]].self, from: basicDictData)
|
|
|
|
expect(result).to(equal(["spam": ["a", "b"]]))
|
|
}
|
|
|
|
// MARK: -- decodes a decodable type
|
|
it("decodes a decodable type") {
|
|
let data: Data = "d8:intValuei100e11:stringValue4:Test".data(using: .utf8)!
|
|
let result: TestType? = try? Bencode.decode(TestType.self, from: data)
|
|
|
|
expect(result).to(equal(TestType(intValue: 100, stringValue: "Test")))
|
|
}
|
|
|
|
// MARK: -- decodes a stringified decodable type
|
|
it("decodes a stringified decodable type") {
|
|
let data: Data = "37:{\"intValue\":100,\"stringValue\":\"Test\"}".data(using: .utf8)!
|
|
let result: TestType? = try? Bencode.decode(TestType.self, from: data)
|
|
|
|
expect(result).to(equal(TestType(intValue: 100, stringValue: "Test")))
|
|
}
|
|
}
|
|
|
|
// MARK: - when decoding a response
|
|
context("when decoding a response") {
|
|
// MARK: -- with a decodable type
|
|
context("with a decodable type") {
|
|
// MARK: ---- decodes successfully
|
|
it("decodes successfully") {
|
|
let data: Data = "ld8:intValuei100e11:stringValue4:Teste5:\u{01}\u{02}\u{03}\u{04}\u{05}e"
|
|
.data(using: .utf8)!
|
|
let result: BencodeResponse<TestType>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: TestType(
|
|
intValue: 100,
|
|
stringValue: "Test"
|
|
),
|
|
data: Data([1, 2, 3, 4, 5])
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: -- decodes successfully with no body
|
|
it("decodes successfully with no body") {
|
|
let data: Data = "ld8:intValuei100e11:stringValue4:Teste"
|
|
.data(using: .utf8)!
|
|
let result: BencodeResponse<TestType>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: TestType(
|
|
intValue: 100,
|
|
stringValue: "Test"
|
|
),
|
|
data: nil
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: ---- throws a parsing error when given an invalid length
|
|
it("throws a parsing error when given an invalid length") {
|
|
let data: Data = "ld12:intValuei100e11:stringValue4:Teste5:\u{01}\u{02}\u{03}\u{04}\u{05}e"
|
|
.data(using: .utf8)!
|
|
|
|
expect {
|
|
let result: BencodeResponse<TestType> = try Bencode.decodeResponse(from: data)
|
|
_ = result
|
|
}.to(throwError(HTTPError.parsingFailed))
|
|
}
|
|
|
|
// MARK: ---- throws a parsing error when given an invalid key
|
|
it("throws a parsing error when given an invalid key") {
|
|
let data: Data = "ld7:INVALIDi100e11:stringValue4:Teste5:\u{01}\u{02}\u{03}\u{04}\u{05}e"
|
|
.data(using: .utf8)!
|
|
|
|
expect {
|
|
let result: BencodeResponse<TestType> = try Bencode.decodeResponse(from: data)
|
|
_ = result
|
|
}.to(throwError(HTTPError.parsingFailed))
|
|
}
|
|
|
|
// MARK: ---- decodes correctly when trying to decode an int to a bool with custom handling
|
|
it("decodes correctly when trying to decode an int to a bool with custom handling") {
|
|
let data: Data = "ld9:boolValuei1e11:stringValue4:testee"
|
|
.data(using: .utf8)!
|
|
|
|
expect {
|
|
let result: BencodeResponse<TestType3> = try Bencode.decodeResponse(from: data)
|
|
_ = result
|
|
}.toNot(throwError(HTTPError.parsingFailed))
|
|
}
|
|
|
|
// MARK: ---- throws a parsing error when trying to decode an int to a bool
|
|
it("throws a parsing error when trying to decode an int to a bool") {
|
|
let data: Data = "ld9:boolValuei1e11:stringValue4:testee"
|
|
.data(using: .utf8)!
|
|
|
|
expect {
|
|
let result: BencodeResponse<TestType2> = try Bencode.decodeResponse(from: data)
|
|
_ = result
|
|
}.to(throwError(HTTPError.parsingFailed))
|
|
}
|
|
}
|
|
|
|
// MARK: -- with stringified json info
|
|
context("with stringified json info") {
|
|
// MARK: -- decodes successfully
|
|
it("decodes successfully") {
|
|
let data: Data = "l37:{\"intValue\":100,\"stringValue\":\"Test\"}5:\u{01}\u{02}\u{03}\u{04}\u{05}e"
|
|
.data(using: .utf8)!
|
|
let result: BencodeResponse<TestType>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: TestType(
|
|
intValue: 100,
|
|
stringValue: "Test"
|
|
),
|
|
data: Data([1, 2, 3, 4, 5])
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: -- decodes successfully with no body
|
|
it("decodes successfully with no body") {
|
|
let data: Data = "l37:{\"intValue\":100,\"stringValue\":\"Test\"}e"
|
|
.data(using: .utf8)!
|
|
let result: BencodeResponse<TestType>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: TestType(
|
|
intValue: 100,
|
|
stringValue: "Test"
|
|
),
|
|
data: nil
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: -- throws a parsing error when invalid
|
|
it("throws a parsing error when invalid") {
|
|
let data: Data = "l36:{\"INVALID\":100,\"stringValue\":\"Test\"}5:\u{01}\u{02}\u{03}\u{04}\u{05}e"
|
|
.data(using: .utf8)!
|
|
|
|
expect {
|
|
let result: BencodeResponse<TestType> = try Bencode.decodeResponse(from: data)
|
|
_ = result
|
|
}.to(throwError(HTTPError.parsingFailed))
|
|
}
|
|
}
|
|
|
|
// MARK: -- with a string value
|
|
context("with a string value") {
|
|
// MARK: ---- decodes successfully
|
|
it("decodes successfully") {
|
|
let data: Data = "l4:Test5:\u{01}\u{02}\u{03}\u{04}\u{05}e".data(using: .utf8)!
|
|
let result: BencodeResponse<String>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: "Test",
|
|
data: Data([1, 2, 3, 4, 5])
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: ---- decodes successfully with no body
|
|
it("decodes successfully with no body") {
|
|
let data: Data = "l4:Teste".data(using: .utf8)!
|
|
let result: BencodeResponse<String>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: "Test",
|
|
data: nil
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: ---- throws a parsing error when invalid
|
|
it("throws a parsing error when invalid") {
|
|
let data: Data = "l10:Teste".data(using: .utf8)!
|
|
|
|
expect {
|
|
let result: BencodeResponse<String> = try Bencode.decodeResponse(from: data)
|
|
_ = result
|
|
}.to(throwError(HTTPError.parsingFailed))
|
|
}
|
|
}
|
|
|
|
// MARK: -- with an int value
|
|
context("with an int value") {
|
|
// MARK: ---- decodes successfully
|
|
it("decodes successfully") {
|
|
let data: Data = "li100e5:\u{01}\u{02}\u{03}\u{04}\u{05}e".data(using: .utf8)!
|
|
let result: BencodeResponse<Int>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: 100,
|
|
data: Data([1, 2, 3, 4, 5])
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: ---- decodes successfully with no body
|
|
it("decodes successfully with no body") {
|
|
let data: Data = "li100ee".data(using: .utf8)!
|
|
let result: BencodeResponse<Int>? = try? Bencode.decodeResponse(from: data)
|
|
|
|
expect(result)
|
|
.to(equal(
|
|
BencodeResponse(
|
|
info: 100,
|
|
data: nil
|
|
)
|
|
))
|
|
}
|
|
|
|
// MARK: ---- throws a parsing error when invalid
|
|
it("throws a parsing error when invalid") {
|
|
let data: Data = "l4:Teste".data(using: .utf8)!
|
|
|
|
expect {
|
|
let result: BencodeResponse<Int> = try Bencode.decodeResponse(from: data)
|
|
_ = result
|
|
}.to(throwError(HTTPError.parsingFailed))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|