Committing the complete mess. I managed to trial&error on converting the php fantasy dictionaries into structs. Though some of the field types are mere blind guesses, so fingers crossed.
Signed-off-by: Adam Rocska <adam.rocska@adams.solutions>
This commit is contained in:
parent
1bf6817aab
commit
e1a5976007
|
@ -1,6 +1,7 @@
|
|||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="rocskaadam">
|
||||
<words>
|
||||
<w>geoname</w>
|
||||
<w>hexadectet</w>
|
||||
<w>peekable</w>
|
||||
<w>uniquing</w>
|
||||
|
|
|
@ -1,8 +1,37 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
public struct CityModel {
|
||||
let city: CityRecord
|
||||
let location: LocationRecord
|
||||
let postal: PostalRecord
|
||||
let mostSpecificSubdivision: SubdivisionRecord
|
||||
let subdivisions: [SubdivisionRecord]
|
||||
var mostSpecificSubdivision: SubdivisionRecord {
|
||||
get {
|
||||
return subdivisions.last ?? SubdivisionRecord(nil)
|
||||
}
|
||||
}
|
||||
|
||||
public init(
|
||||
city: CityRecord,
|
||||
location: LocationRecord,
|
||||
postal: PostalRecord,
|
||||
subdivisions: [SubdivisionRecord]
|
||||
) {
|
||||
self.city = city
|
||||
self.location = location
|
||||
self.postal = postal
|
||||
self.subdivisions = subdivisions
|
||||
}
|
||||
|
||||
init(_ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
city: CityRecord(dictionary?["city"]?.unwrap()),
|
||||
location: LocationRecord(dictionary?["location"]?.unwrap()),
|
||||
postal: PostalRecord(dictionary?["postal"]?.unwrap()),
|
||||
subdivisions: (dictionary?["subdivisions"]?.unwrap() ?? [] as [Payload]).compactMap(
|
||||
{ SubdivisionRecord($0.unwrap()) }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,142 @@ public class CityFileBased {
|
|||
public var metadata: DbMetadata { get { return dbReader.metadata } }
|
||||
|
||||
public init(dbReader: Reader) {
|
||||
precondition(dbReader.metadata.databaseType == CityFileBased.databaseType.rawValue)
|
||||
// php scripter style validation. Dumb as a rock, but that's what MaxMind implemented, and therefore expects.
|
||||
precondition(dbReader.metadata.databaseType.contains(CityFileBased.databaseType.rawValue))
|
||||
self.dbReader = dbReader
|
||||
}
|
||||
|
||||
public func lookup(_ ip: IpAddress) -> CityModel? {
|
||||
guard let dictionary = dbReader.get(ip) else { return nil }
|
||||
// print(dictionary)
|
||||
let model = CityModel(dictionary)
|
||||
print(model)
|
||||
// ["location": Decoder.Payload.map(
|
||||
// ["time_zone": Decoder.Payload.utf8String("Europe/Budapest"),
|
||||
// "longitude": Decoder.Payload.double(19.0404),
|
||||
// "latitude": Decoder.Payload.double(47.4984),
|
||||
// "accuracy_radius": Decoder.Payload.uInt16(20)]
|
||||
// ),
|
||||
// "continent": Decoder.Payload.map(
|
||||
// ["geoname_id": Decoder.Payload.uInt32(6255148),
|
||||
// "code": Decoder.Payload.utf8String("EU"),
|
||||
// "names": Decoder.Payload.map(
|
||||
// [
|
||||
// "es": Decoder.Payload.utf8String("Europa"),
|
||||
// "fr": Decoder.Payload.utf8String("Europe"),
|
||||
// "ru": Decoder.Payload.utf8String("Европа"),
|
||||
// "pt-BR": Decoder.Payload.utf8String("Europa"),
|
||||
// "ja": Decoder.Payload.utf8String("ヨーロッパ"),
|
||||
// "zh-CN": Decoder.Payload.utf8String("欧洲"),
|
||||
// "de": Decoder.Payload.utf8String("Europa"),
|
||||
// "en": Decoder.Payload.utf8String("Europe")
|
||||
// ]
|
||||
// )]
|
||||
// ),
|
||||
// "country": Decoder.Payload.map(
|
||||
// ["names": Decoder.Payload.map(
|
||||
// ["es": Decoder.Payload.utf8String("Hungría"),
|
||||
// "ja": Decoder.Payload.utf8String(
|
||||
// "ハンガリー共和国"
|
||||
// ),
|
||||
// "en": Decoder.Payload.utf8String("Hungary"),
|
||||
// "ru": Decoder.Payload.utf8String(
|
||||
// "Венгрия"
|
||||
// ),
|
||||
// "pt-BR": Decoder.Payload.utf8String("Hungria"),
|
||||
// "zh-CN": Decoder.Payload.utf8String(
|
||||
// "匈牙利"
|
||||
// ),
|
||||
// "de": Decoder.Payload.utf8String("Ungarn"),
|
||||
// "fr": Decoder.Payload.utf8String("Hongrie")]
|
||||
// ),
|
||||
// "is_in_european_union": Decoder.Payload.boolean(true),
|
||||
// "iso_code": Decoder.Payload.utf8String(
|
||||
// "HU"
|
||||
// ),
|
||||
// "geoname_id": Decoder.Payload.uInt32(719819)]
|
||||
// ),
|
||||
// "subdivisions": Decoder.Payload.array(
|
||||
// [Decoder.Payload.map(
|
||||
// ["geoname_id": Decoder.Payload.uInt32(3054638),
|
||||
// "iso_code": Decoder.Payload.utf8String(
|
||||
// "BU"
|
||||
// ),
|
||||
// "names": Decoder.Payload.map(["en": Decoder.Payload.utf8String("Budapest")])]
|
||||
// )]
|
||||
// ),
|
||||
// "city": Decoder.Payload.map(
|
||||
// ["geoname_id": Decoder.Payload.uInt32(3054643),
|
||||
// "names": Decoder.Payload.map(
|
||||
// ["ja": Decoder.Payload.utf8String("ブダペスト"),
|
||||
// "es": Decoder.Payload.utf8String(
|
||||
// "Budapest"
|
||||
// ),
|
||||
// "ru": Decoder.Payload.utf8String("Будапешт"),
|
||||
// "de": Decoder.Payload.utf8String(
|
||||
// "Budapest"
|
||||
// ),
|
||||
// "en": Decoder.Payload.utf8String("Budapest"),
|
||||
// "fr": Decoder.Payload.utf8String(
|
||||
// "Budapest"
|
||||
// ),
|
||||
// "zh-CN": Decoder.Payload.utf8String("布达佩斯"),
|
||||
// "pt-BR": Decoder.Payload.utf8String("Budapeste")]
|
||||
// )]
|
||||
// ),
|
||||
// "registered_country": Decoder.Payload.map(
|
||||
// ["geoname_id": Decoder.Payload.uInt32(719819),
|
||||
// "is_in_european_union": Decoder.Payload.boolean(
|
||||
// true
|
||||
// ),
|
||||
// "iso_code": Decoder.Payload.utf8String("HU"),
|
||||
// "names": Decoder.Payload.map(
|
||||
// ["de": Decoder.Payload.utf8String("Ungarn"),
|
||||
// "zh-CN": Decoder.Payload.utf8String(
|
||||
// "匈牙利"
|
||||
// ),
|
||||
// "fr": Decoder.Payload.utf8String("Hongrie"),
|
||||
// "ru": Decoder.Payload.utf8String(
|
||||
// "Венгрия"
|
||||
// ),
|
||||
// "pt-BR": Decoder.Payload.utf8String("Hungria"),
|
||||
// "en": Decoder.Payload.utf8String(
|
||||
// "Hungary"
|
||||
// ),
|
||||
// "es": Decoder.Payload.utf8String("Hungría"),
|
||||
// "ja": Decoder.Payload.utf8String("ハンガリー共和国")]
|
||||
// )]
|
||||
// ),
|
||||
// "postal": Decoder.Payload.map(["code": Decoder.Payload.utf8String("1096")])]
|
||||
|
||||
|
||||
|
||||
// CityModel(
|
||||
// city: CityRecord(
|
||||
// confidence: <#T##Int?##Swift.Int?#>,
|
||||
// geonameId: <#T##Int?##Swift.Int?#>,
|
||||
// name: <#T##String?##Swift.String?#>,
|
||||
// names: <#T##[String: String]?##[Swift.String: Swift.String]?#>
|
||||
// ),
|
||||
// location: LocationRecord(
|
||||
// averageIncome: <#T##Int?##Swift.Int?#>,
|
||||
// accuracyRadius: <#T##Int?##Swift.Int?#>,
|
||||
// latitude: <#T##Float?##Swift.Float?#>,
|
||||
// longitude: <#T##Float?##Swift.Float?#>,
|
||||
// populationDensity: <#T##Int?##Swift.Int?#>,
|
||||
// metroCode: <#T##Int?##Swift.Int?#>,
|
||||
// timeZone: <#T##String?##Swift.String?#>
|
||||
// ),
|
||||
// postal: PostalRecord(code: <#T##String?##Swift.String?#>,
|
||||
// confidence: <#T##Int?##Swift.Int?#>),
|
||||
// mostSpecificSubdivision: SubdivisionRecord(
|
||||
// confidence: <#T##Int?##Swift.Int?#>,
|
||||
// geonameId: <#T##Int?##Swift.Int?#>,
|
||||
// isoCode: <#T##String?##Swift.String?#>,
|
||||
// name: <#T##String?##Swift.String?#>,
|
||||
// names: <#T##[String: String]?##[Swift.String: Swift.String]?#>
|
||||
// )
|
||||
// )
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,24 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
// WTF! SRSLY!
|
||||
public struct CityRecord {
|
||||
let confidence: Int?
|
||||
let geonameId: Int?
|
||||
let name: String?
|
||||
// assumed
|
||||
let confidence: UInt8?
|
||||
let geonameId: UInt32?
|
||||
let names: [String: String]?
|
||||
var name: String? { get { return names?["en"] } }
|
||||
|
||||
public init(confidence: UInt8?, geonameId: UInt32?, names: [String: String]?) {
|
||||
self.confidence = confidence
|
||||
self.geonameId = geonameId
|
||||
self.names = names
|
||||
}
|
||||
|
||||
init(_ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
confidence: dictionary?["confidence"]?.unwrap(),
|
||||
geonameId: dictionary?["geoname_id"]?.unwrap(),
|
||||
names: (dictionary?["names"]?.unwrap() ?? [:] as [String: Payload]).compactMapValues({ $0.unwrap() })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
public struct ContinentRecord {
|
||||
let code: String?
|
||||
let geonameId: Int?
|
||||
let name: String?
|
||||
let geonameId: UInt32?
|
||||
let names: [String: String]?
|
||||
var name: String? { get { return names?["en"] } }
|
||||
|
||||
public init(code: String?, geonameId: UInt32?, names: [String: String]?) {
|
||||
self.code = code
|
||||
self.geonameId = geonameId
|
||||
self.names = names
|
||||
}
|
||||
|
||||
init(_ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
code: dictionary?["code"]?.unwrap(),
|
||||
geonameId: dictionary?["geoname_id"]?.unwrap(),
|
||||
names: (dictionary?["names"]?.unwrap() ?? [:] as [String: Payload]).compactMapValues({ $0.unwrap() })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,35 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
public struct CountryRecord {
|
||||
// CONFIDENCE BEING AN INT?! ARE YOU FUCKING KIDDING ME! AND IT'S OPTIONAL.
|
||||
let confidence: Int?
|
||||
let geonameId: Int?
|
||||
// At least the bool isn't optional. Thank's php people. 👍 🖕
|
||||
let confidence: UInt8?
|
||||
let geonameId: UInt32?
|
||||
let isInEuropeanUnion: Bool
|
||||
let isoCode: String?
|
||||
let name: String?
|
||||
let names: [String: String]?
|
||||
var name: String? { get { return names?["en"] } }
|
||||
|
||||
public init(
|
||||
confidence: UInt8?,
|
||||
geonameId: UInt32?,
|
||||
isInEuropeanUnion: Bool,
|
||||
isoCode: String?,
|
||||
names: [String: String]?
|
||||
) {
|
||||
self.confidence = confidence
|
||||
self.geonameId = geonameId
|
||||
self.isInEuropeanUnion = isInEuropeanUnion
|
||||
self.isoCode = isoCode
|
||||
self.names = names
|
||||
}
|
||||
|
||||
init(_ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
confidence: dictionary?["confidence"]?.unwrap(),
|
||||
geonameId: dictionary?["geoname_id"]?.unwrap(),
|
||||
isInEuropeanUnion: dictionary?["is_in_european_union"]?.unwrap() ?? false,
|
||||
isoCode: dictionary?["iso_code"]?.unwrap(),
|
||||
names: (dictionary?["names"]?.unwrap() ?? [:] as [String: Payload]).compactMapValues({ $0.unwrap() })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,45 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
public struct LocationRecord {
|
||||
let averageIncome: Int?
|
||||
let accuracyRadius: Int?
|
||||
let latitude: Float?
|
||||
let longitude: Float?
|
||||
let populationDensity: Int?
|
||||
let metroCode: Int?
|
||||
// assumed
|
||||
let averageIncome: UInt32?
|
||||
let accuracyRadius: UInt16?
|
||||
let latitude: Double?
|
||||
let longitude: Double?
|
||||
// assumed
|
||||
let populationDensity: UInt16?
|
||||
// assumed
|
||||
let metroCode: UInt16?
|
||||
let timeZone: String?
|
||||
|
||||
public init(
|
||||
averageIncome: UInt32?,
|
||||
accuracyRadius: UInt16?,
|
||||
latitude: Double?,
|
||||
longitude: Double?,
|
||||
populationDensity: UInt16?,
|
||||
metroCode: UInt16?,
|
||||
timeZone: String?
|
||||
) {
|
||||
self.averageIncome = averageIncome
|
||||
self.accuracyRadius = accuracyRadius
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
self.populationDensity = populationDensity
|
||||
self.metroCode = metroCode
|
||||
self.timeZone = timeZone
|
||||
}
|
||||
|
||||
init(_ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
averageIncome: dictionary?["average_income"]?.unwrap(),
|
||||
accuracyRadius: dictionary?["accuracy_radius"]?.unwrap(),
|
||||
latitude: dictionary?["latitude"]?.unwrap(),
|
||||
longitude: dictionary?["longitude"]?.unwrap(),
|
||||
populationDensity: dictionary?["population_density"]?.unwrap(),
|
||||
metroCode: dictionary?["metro_code"]?.unwrap(),
|
||||
timeZone: dictionary?["time_zone"]?.unwrap()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Foundation
|
||||
|
||||
public struct MaxMindRecord {
|
||||
// I don't even know any more what to say. Stupidest shit I saw in years.
|
||||
let queriesRemaining: Int?
|
||||
// assumed
|
||||
let queriesRemaining: UInt16?
|
||||
}
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
public struct PostalRecord {
|
||||
let code:String?
|
||||
let confidence:Int?
|
||||
let code: String?
|
||||
// assumed
|
||||
let confidence: UInt8?
|
||||
|
||||
public init(code: String?, confidence: UInt8?) {
|
||||
self.code = code
|
||||
self.confidence = confidence
|
||||
}
|
||||
|
||||
init(_ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
code: dictionary?["code"]?.unwrap(),
|
||||
confidence: dictionary?["confidence"]?.unwrap()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Foundation
|
||||
|
||||
// TODO: WTF
|
||||
public struct RepresentedCountryRecord {
|
||||
let type: String?
|
||||
}
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
public struct SubdivisionRecord {
|
||||
let confidence: Int?
|
||||
let geonameId: Int?
|
||||
// Assumed
|
||||
let confidence: UInt8?
|
||||
let geonameId: UInt32?
|
||||
let isoCode: String?
|
||||
let name: String?
|
||||
let names: [String: String]?
|
||||
var name: String? { get { return names?["en"] } }
|
||||
|
||||
public init(confidence: UInt8?, geonameId: UInt32?, isoCode: String?, names: [String: String]?) {
|
||||
self.confidence = confidence
|
||||
self.geonameId = geonameId
|
||||
self.isoCode = isoCode
|
||||
self.names = names
|
||||
}
|
||||
|
||||
init(_ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
confidence: dictionary?["confidence"]?.unwrap(),
|
||||
geonameId: dictionary?["geoname_id"]?.unwrap(),
|
||||
isoCode: dictionary?["iso_cod"]?.unwrap(),
|
||||
names: (dictionary?["names"]?.unwrap() ?? [:] as [String: Payload]).compactMapValues({ $0.unwrap() })
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import protocol DataSection.DataSection
|
|||
import protocol IndexReader.Index
|
||||
import struct MetadataReader.Metadata
|
||||
|
||||
public class InMemoryReader<SearchIndex>: Reader where SearchIndex: IndexReader.Index {
|
||||
class Mediator<SearchIndex>: Reader where SearchIndex: IndexReader.Index {
|
||||
|
||||
private let index: SearchIndex
|
||||
public let metadata: Metadata
|
|
@ -3,12 +3,15 @@ import class DataSection.InMemoryDataSection
|
|||
import class IndexReader.InMemoryIndex
|
||||
import class MetadataReader.Reader
|
||||
|
||||
class ReaderFactory {
|
||||
func makeInMemoryReader(_ inputStream: @escaping () -> InputStream) throws -> Reader {
|
||||
public class ReaderFactory {
|
||||
|
||||
public init() {}
|
||||
|
||||
public func makeInMemoryReader(_ inputStream: @escaping () -> InputStream) throws -> Reader {
|
||||
let reader = MetadataReader.Reader(windowSize: 2048)
|
||||
guard let metadata = reader.read(inputStream()) else { throw ReaderError.cantExtractMetadata }
|
||||
let inMemoryIndex = InMemoryIndex<UInt>(metadata: metadata, stream: inputStream())
|
||||
let inMemoryDataSection = InMemoryDataSection(metadata: metadata, stream: inputStream())
|
||||
return InMemoryReader(index: inMemoryIndex, dataSection: inMemoryDataSection, metadata: metadata)
|
||||
return Mediator(index: inMemoryIndex, dataSection: inMemoryDataSection, metadata: metadata)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
extension Data {
|
||||
|
||||
func chunked(into size: Int) -> [Data] {
|
||||
precondition(size > 0, "Can't chunk data into 0 sized chunks.")
|
||||
precondition(size <= count, "Can't chunk data into chunks of greater size.")
|
||||
precondition(count % size == 0, "Data is not divisible into \(size)sized chunks.")
|
||||
var bounds = (
|
||||
lower: startIndex,
|
||||
upper: index(startIndex, offsetBy: size, limitedBy: endIndex) ?? endIndex
|
||||
)
|
||||
var result: [Data] = []
|
||||
while bounds.lower != endIndex {
|
||||
result.append(subdata(in: Range(uncheckedBounds: bounds)))
|
||||
bounds = (
|
||||
lower: bounds.upper,
|
||||
upper: index(bounds.upper, offsetBy: size, limitedBy: endIndex) ?? endIndex
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,8 @@ import enum IndexReader.IpAddress
|
|||
import enum Decoder.Payload
|
||||
@testable import struct MetadataReader.Metadata
|
||||
|
||||
import class DBReader.ReaderFactory
|
||||
|
||||
class CityFileBasedTest: XCTestCase {
|
||||
|
||||
let stubMetadata = Metadata(
|
||||
|
@ -43,6 +45,20 @@ class CityFileBasedTest: XCTestCase {
|
|||
XCTAssertTrue(getWasCalled)
|
||||
}
|
||||
|
||||
func testLookup_wut() throws {
|
||||
let factory = ReaderFactory()
|
||||
let streamFactory: () -> InputStream = {
|
||||
InputStream(
|
||||
fileAtPath: "/Users/rocskaadam/src/adam-rocska/src/GeoIP2-swift/Tests/ApiTests/Resources/GeoLite2-City_20200526/GeoLite2-City.mmdb"
|
||||
// fileAtPath: "/Users/rocskaadam/src/adam-rocska/src/GeoIP2-swift/Tests/ApiTests/Resources/GeoLite2-ASN_20200526/GeoLite2-ASN.mmdb"
|
||||
// fileAtPath: "/Users/rocskaadam/src/adam-rocska/src/GeoIP2-swift/Tests/DBReaderTests/Resources/GeoLite2-Country_20200421/GeoLite2-Country.mmdb"
|
||||
)!
|
||||
}
|
||||
let reader = try factory.makeInMemoryReader(streamFactory)
|
||||
let cityFileBased = CityFileBased(dbReader: reader)
|
||||
cityFileBased.lookup(.v4("80.99.18.166"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MockReader: DBReader.Reader {
|
||||
|
|
|
@ -7,7 +7,7 @@ import protocol DataSection.DataSection
|
|||
import protocol IndexReader.Index
|
||||
@testable import struct MetadataReader.Metadata
|
||||
|
||||
class InMemoryReaderTest: XCTestCase {
|
||||
class MediatorTest: XCTestCase {
|
||||
|
||||
private let stubMetadata = Metadata(
|
||||
nodeCount: 123,
|
||||
|
@ -31,7 +31,7 @@ class InMemoryReaderTest: XCTestCase {
|
|||
mockSearchIndexLookupCalled = true
|
||||
return nil
|
||||
}
|
||||
let reader = InMemoryReader(index: mockSearchIndex, dataSection: MockDataSection(), metadata: stubMetadata)
|
||||
let reader = Mediator(index: mockSearchIndex, dataSection: MockDataSection(), metadata: stubMetadata)
|
||||
XCTAssertNil(reader.get(expectedIp))
|
||||
XCTAssertTrue(mockSearchIndexLookupCalled)
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class InMemoryReaderTest: XCTestCase {
|
|||
mockDataSectionCalled = true
|
||||
return nil
|
||||
}
|
||||
let reader = InMemoryReader(index: mockSearchIndex, dataSection: mockDataSection, metadata: stubMetadata)
|
||||
let reader = Mediator(index: mockSearchIndex, dataSection: mockDataSection, metadata: stubMetadata)
|
||||
XCTAssertNil(reader.get(expectedIp))
|
||||
XCTAssertTrue(mockSearchIndexLookupCalled)
|
||||
XCTAssertTrue(mockDataSectionCalled)
|
||||
|
@ -75,7 +75,7 @@ class InMemoryReaderTest: XCTestCase {
|
|||
mockDataSectionCalled = true
|
||||
return expectedLookupResult
|
||||
}
|
||||
let reader = InMemoryReader(index: mockSearchIndex, dataSection: mockDataSection, metadata: stubMetadata)
|
||||
let reader = Mediator(index: mockSearchIndex, dataSection: mockDataSection, metadata: stubMetadata)
|
||||
XCTAssertEqual(expectedLookupResult, reader.get(expectedIp))
|
||||
XCTAssertTrue(mockSearchIndexLookupCalled)
|
||||
XCTAssertTrue(mockDataSectionCalled)
|
|
@ -1,18 +0,0 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
@testable import IndexReader
|
||||
|
||||
class DataTest: XCTestCase {
|
||||
|
||||
func testChunked() {
|
||||
let data = Data([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
||||
let chunked = data.chunked(into: 2)
|
||||
XCTAssertEqual(Data([1, 2]), chunked[0])
|
||||
XCTAssertEqual(Data([3, 4]), chunked[1])
|
||||
XCTAssertEqual(Data([5, 6]), chunked[2])
|
||||
XCTAssertEqual(Data([7, 8]), chunked[3])
|
||||
XCTAssertEqual(Data([9, 10]), chunked[4])
|
||||
XCTAssertEqual(5, chunked.count)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
|
||||
/Library/Developer/Toolchains/swift-5.0.3-RELEASE.xctoolchain/usr/bin/swift test \
|
||||
--enable-code-coverage \
|
||||
--parallel \
|
||||
--num-workers 4
|
||||
|
||||
reset
|
||||
|
||||
llvm-cov report \
|
||||
.build/x86_64-apple-macosx/debug/GeoIP2PackageTests.xctest/Contents/MacOS/GeoIP2PackageTests \
|
||||
-instr-profile=.build/x86_64-apple-macosx/debug/codecov/default.profdata \
|
||||
-ignore-filename-regex=".build|Tests" \
|
||||
-use-color
|
Loading…
Reference in New Issue