This repository has been archived by the owner. It is now read-only.
Permalink
Cannot retrieve contributors at this time
108 lines (86 sloc)
4.9 KB
| /* This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| import Foundation | |
| import Shared | |
| @testable import Sync | |
| import XCTest | |
| import SwiftyJSON | |
| // Always return a gigantic encoded payload. | |
| func massivify(record: Record<CleartextPayloadJSON>) -> JSON? { | |
| return JSON([ | |
| "id": record.id, | |
| "foo": String(repeating: "X", count: Sync15StorageClient.maxRecordSizeBytes + 1) | |
| ]) | |
| } | |
| class StorageClientTests: XCTestCase { | |
| func testPartialJSON() { | |
| let body = "0" | |
| let o: Any? = try! JSONSerialization.jsonObject(with: body.data(using: .utf8)!, options: .allowFragments) | |
| XCTAssertTrue(JSON(o!).isInt()) | |
| } | |
| func testPOSTResult() { | |
| // Pulled straight from <http://docs.services.mozilla.com/storage/apis-1.5.html>. | |
| let r = "{" + | |
| "\"success\": [\"GXS58IDC_12\", \"GXS58IDC_13\", \"GXS58IDC_15\"," + | |
| "\"GXS58IDC_16\", \"GXS58IDC_18\", \"GXS58IDC_19\"]," + | |
| "\"failed\": {\"GXS58IDC_11\": \"invalid ttl\"," + | |
| "\"GXS58IDC_14\": \"invalid sortindex\"}" + | |
| "}" | |
| let p = POSTResult.fromJSON(JSON(parseJSON: r)) | |
| XCTAssertTrue(p != nil) | |
| XCTAssertEqual(p!.success[0], "GXS58IDC_12") | |
| XCTAssertEqual(p!.failed["GXS58IDC_14"]!, "invalid sortindex") | |
| XCTAssertTrue(nil == POSTResult.fromJSON(JSON(parseJSON: "{\"foo\": 5}"))) | |
| } | |
| func testNumeric() { | |
| let m = ResponseMetadata(status: 200, headers: [ | |
| "X-Last-Modified": "2174380461.12", | |
| ]) | |
| XCTAssertTrue(m.lastModifiedMilliseconds == 2174380461120) | |
| XCTAssertEqual("2174380461.12", millisecondsToDecimalSeconds(2174380461120)) | |
| } | |
| // Trivial test for struct semantics that we might want to pay attention to if they change, | |
| // and for response header parsing. | |
| func testResponseHeaders() { | |
| let v: JSON = JSON(parseJSON: "{\"a:\": 2}") | |
| let m = ResponseMetadata(status: 200, headers: [ | |
| "X-Weave-Timestamp": "1274380461.12", | |
| "X-Last-Modified": "2174380461.12", | |
| "X-Weave-Next-Offset": "abdef", | |
| ]) | |
| XCTAssertTrue(m.lastModifiedMilliseconds == 2174380461120) | |
| XCTAssertTrue(m.timestampMilliseconds == 1274380461120) | |
| XCTAssertTrue(m.nextOffset == "abdef") | |
| // Just to avoid consistent overflow allowing ==. | |
| XCTAssertTrue(m.lastModifiedMilliseconds?.description == "2174380461120") | |
| XCTAssertTrue(m.timestampMilliseconds.description == "1274380461120") | |
| let x: StorageResponse<JSON> = StorageResponse<JSON>(value: v, metadata: m) | |
| func doTesting(y: StorageResponse<JSON>) { | |
| // Make sure that reference fields in a struct are copies of the same reference, | |
| // not references to a copy. | |
| XCTAssertTrue(x.value == y.value) | |
| XCTAssertTrue(y.metadata.lastModifiedMilliseconds == x.metadata.lastModifiedMilliseconds, "lastModified is the same.") | |
| XCTAssertTrue(x.metadata.quotaRemaining == nil, "No quota.") | |
| XCTAssertTrue(y.metadata.lastModifiedMilliseconds == 2174380461120, "lastModified is correct.") | |
| XCTAssertTrue(x.metadata.timestampMilliseconds == 1274380461120, "timestamp is correct.") | |
| XCTAssertTrue(x.metadata.nextOffset == "abdef", "nextOffset is correct.") | |
| XCTAssertTrue(x.metadata.records == nil, "No X-Weave-Records.") | |
| } | |
| doTesting(y: x) | |
| } | |
| func testOverSizeRecords() { | |
| let delegate = MockSyncDelegate() | |
| // We can use these useless values because we're directly injecting decrypted | |
| // payloads; no need for real keys etc. | |
| let prefs = MockProfilePrefs() | |
| let scratchpad = Scratchpad(b: KeyBundle.random(), persistingTo: prefs) | |
| let synchronizer = IndependentRecordSynchronizer(scratchpad: scratchpad, delegate: delegate, basePrefs: prefs, why: .scheduled, collection: "foo") | |
| let jA = "{\"id\":\"aaaaaa\",\"histUri\":\"http://foo.com/\",\"title\": \"ñ\",\"visits\":[{\"date\":1222222222222222,\"type\":1}]}" | |
| let rA = Record<CleartextPayloadJSON>(id: "aaaaaa", payload: CleartextPayloadJSON(JSON(parseJSON: jA)), modified: 10000, sortindex: 123, ttl: 1000000) | |
| let storageClient = Sync15StorageClient(serverURI: "http://example.com/".asURL!, authorizer: identity, workQueue: DispatchQueue.main, resultQueue: DispatchQueue.main, backoff: MockBackoffStorage()) | |
| let collectionClient = storageClient.clientForCollection("foo", encrypter: RecordEncrypter<CleartextPayloadJSON>(serializer: massivify, factory: { CleartextPayloadJSON($0) })) | |
| let result = synchronizer.uploadRecords([rA], lastTimestamp: Date.now(), storageClient: collectionClient, onUpload: { _,_ in deferMaybe(Date.now()) }) | |
| XCTAssertTrue(result.value.failureValue is RecordTooLargeError) | |
| } | |
| } |