Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cf0fbeb

Browse files
committedJul 11, 2018
## 1.1.0
### Added * Add **swiftlint** & **swiftformat** to build phases * ```OneWaySynchronizer.cancel()``` * ```OwsError.cancelledError``` * ```OneWaySynchronizerProcessor.owsPrepareDownload(of descriptions: [OneWaySynchronizerItemDescription], completion: @escaping OwsItemsCompletion)```
1 parent d71d694 commit cf0fbeb

File tree

10 files changed

+542
-204
lines changed

10 files changed

+542
-204
lines changed
 

‎.travis.yml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
language: swift
2+
osx_image: xcode9.4
3+
branches:
4+
only:
5+
- master
6+
before_install:
7+
- gem install cocoapods --pre --no-rdoc --no-ri --no-document --quiet
8+
- pod repo update
9+
script:
10+
- cd Demo && make

‎CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
# CHANGELOG
22

3+
## 1.1.0
4+
### Added
5+
* Add **swiftlint** & **swiftformat** to build phases
6+
* ```OneWaySynchronizer.cancel()```
7+
* ```OwsError.cancelledError```
8+
* ```OneWaySynchronizerProcessor.owsPrepareDownload(of descriptions: [OneWaySynchronizerItemDescription], completion: @escaping OwsItemsCompletion)```
9+
10+
### Changed
11+
* Reformat sources
12+
313
## 1.0.0
414
Initial release

‎Demo/Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
.PHONY: test
3+
4+
test:
5+
pod repo update
6+
pod install
7+
xcodebuild test -quiet -scheme OneWaySynchronizerDemo -workspace ./OneWaySynchronizerDemo.xcworkspace/ -destination 'platform=iOS Simulator,name=iPhone 8' || exit 1

‎Demo/OneWaySynchronizerDemo.xcodeproj/project.pbxproj

+34
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
1246EBD420F4D8A6008F3352 /* OneWaySynchronizerDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneWaySynchronizerDemoTests.swift; sourceTree = "<group>"; };
4141
1246EBD620F4D8A6008F3352 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4242
1246EBDF20F4D900008F3352 /* MyService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyService.swift; sourceTree = "<group>"; };
43+
129DEBC320F60F2400B23035 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = "<group>"; };
44+
129DEBC420F60F2400B23035 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
4345
560D357930ECF0DBA262F9BB /* Pods-OneWaySynchronizerDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneWaySynchronizerDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-OneWaySynchronizerDemo/Pods-OneWaySynchronizerDemo.release.xcconfig"; sourceTree = "<group>"; };
4446
764034DE1CC28CB89E84D4E3 /* Pods_OneWaySynchronizerDemoTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OneWaySynchronizerDemoTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4547
81F2DF9B2667791791120E40 /* Pods-OneWaySynchronizerDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneWaySynchronizerDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-OneWaySynchronizerDemo/Pods-OneWaySynchronizerDemo.debug.xcconfig"; sourceTree = "<group>"; };
@@ -71,6 +73,8 @@
7173
1246EBB320F4D8A5008F3352 = {
7274
isa = PBXGroup;
7375
children = (
76+
129DEBC320F60F2400B23035 /* CHANGELOG.md */,
77+
129DEBC420F60F2400B23035 /* README.md */,
7478
1246EBBE20F4D8A5008F3352 /* OneWaySynchronizerDemo */,
7579
1246EBD320F4D8A6008F3352 /* OneWaySynchronizerDemoTests */,
7680
1246EBBD20F4D8A5008F3352 /* Products */,
@@ -139,6 +143,8 @@
139143
buildConfigurationList = 1246EBD920F4D8A6008F3352 /* Build configuration list for PBXNativeTarget "OneWaySynchronizerDemo" */;
140144
buildPhases = (
141145
19CD3573778FFB652BE5F783 /* [CP] Check Pods Manifest.lock */,
146+
129DEBC220F60E5900B23035 /* [CUSTOM] Format */,
147+
129DEBC120F606C800B23035 /* [CUSTOM] Linting */,
142148
1246EBB820F4D8A5008F3352 /* Sources */,
143149
1246EBB920F4D8A5008F3352 /* Frameworks */,
144150
1246EBBA20F4D8A5008F3352 /* Resources */,
@@ -234,6 +240,34 @@
234240
/* End PBXResourcesBuildPhase section */
235241

236242
/* Begin PBXShellScriptBuildPhase section */
243+
129DEBC120F606C800B23035 /* [CUSTOM] Linting */ = {
244+
isa = PBXShellScriptBuildPhase;
245+
buildActionMask = 2147483647;
246+
files = (
247+
);
248+
inputPaths = (
249+
);
250+
name = "[CUSTOM] Linting";
251+
outputPaths = (
252+
);
253+
runOnlyForDeploymentPostprocessing = 0;
254+
shellPath = /bin/sh;
255+
shellScript = "if [ \"$TRAVIS\" != \"true\" ]; then\n if which swiftlint >/dev/null; then\n cd ../Source && swiftlint --config ../Demo/swiftlint.yml\n else\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\n fi\nfi";
256+
};
257+
129DEBC220F60E5900B23035 /* [CUSTOM] Format */ = {
258+
isa = PBXShellScriptBuildPhase;
259+
buildActionMask = 2147483647;
260+
files = (
261+
);
262+
inputPaths = (
263+
);
264+
name = "[CUSTOM] Format";
265+
outputPaths = (
266+
);
267+
runOnlyForDeploymentPostprocessing = 0;
268+
shellPath = /bin/sh;
269+
shellScript = "if [ \"$TRAVIS\" != \"true\" ]; then\n if which swiftformat >/dev/null; then\n cd ../Source && swiftformat .\n else\n echo \"warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat\"\n fi\nfi";
270+
};
237271
19CD3573778FFB652BE5F783 /* [CP] Check Pods Manifest.lock */ = {
238272
isa = PBXShellScriptBuildPhase;
239273
buildActionMask = 2147483647;

‎Demo/OneWaySynchronizerDemo/MyService.swift

+10-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ typealias PreviewCompletion = (_ error: Error?, _ image: UIImage?) -> Void
1616

1717
fileprivate struct RemoteItemDescription: OneWaySynchronizerItemDescription {
1818
var owsPrimaryKey: OneWaySynchronizerItemKey
19+
var owsDownloadOrder: OneWaySynchronizerItemDownloadOrder
1920
var order: Int
2021
var title: String
2122
var url: String
@@ -76,7 +77,7 @@ class MyService: OneWaySynchronizerProcessor {
7677

7778
// NOTE: Method can be called not in main thread!
7879

79-
completion() // No matter what thread is now running on!
80+
completion() // Completion can be called from any thread!
8081
}
8182

8283
func owsSyncEnd(_ completion: @escaping OwsCompletion) {
@@ -87,7 +88,7 @@ class MyService: OneWaySynchronizerProcessor {
8788

8889
self._items.sort()
8990

90-
completion() // No matter what thread is now running on!
91+
completion() // Completion can be called from any thread!
9192
}
9293
}
9394

@@ -102,6 +103,7 @@ class MyService: OneWaySynchronizerProcessor {
102103
if let json = response.result.value {
103104
for (i, item) in (json as! [Dictionary<String,Any>]).enumerated() {
104105
items.append(RemoteItemDescription(owsPrimaryKey: String(item["id"] as! Int),
106+
owsDownloadOrder: 0,
105107
order: i,
106108
title: item["login"] as! String,
107109
url: item["avatar_url"] as! String))
@@ -180,10 +182,15 @@ class MyService: OneWaySynchronizerProcessor {
180182

181183
completion(nil) // No matter what thread is now running on!
182184
}
183-
184185

185186
}
186187

188+
func owsPrepareDownload(of descriptions: [OneWaySynchronizerItemDescription], completion: @escaping OwsItemsCompletion) {
189+
completion(nil, descriptions)
190+
}
191+
192+
// MARK: Public
193+
187194
func count() -> Int {
188195
return _items.count
189196
}

‎Demo/OneWaySynchronizerDemoTests/OneWaySynchronizerDemoTests.swift

+88-8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ func isDownloadContentError(_ err: Error?, key: OneWaySynchronizerItemKey, under
4343
}
4444
}
4545

46+
func isCancelError(_ err: Error?) -> Bool {
47+
guard let err = err as? OwsError else {
48+
return false
49+
}
50+
switch err {
51+
case .cancelledError:
52+
return true
53+
default:
54+
return false
55+
}
56+
}
57+
4658
class TestItem: OneWaySynchronizerItemDescription {
4759

4860
func vss_shouldBeUpdated(with remoteItem: TestItem) -> Bool {
@@ -51,11 +63,19 @@ class TestItem: OneWaySynchronizerItemDescription {
5163

5264
typealias K = String
5365

54-
var owsPrimaryKey: String
66+
var owsPrimaryKey: OneWaySynchronizerItemKey
67+
var owsDownloadOrder: OneWaySynchronizerItemDownloadOrder
5568
let downloadError: Error?
5669

70+
init(key: String, order: Int, downloadError: Error? = nil ) {
71+
owsPrimaryKey = key
72+
owsDownloadOrder = order
73+
self.downloadError = downloadError
74+
}
75+
5776
init(key: String, downloadError: Error? = nil ) {
5877
owsPrimaryKey = key
78+
owsDownloadOrder = 0
5979
self.downloadError = downloadError
6080
}
6181
}
@@ -69,11 +89,11 @@ class TestProcessor: OneWaySynchronizerProcessor {
6989

7090
var beginCalled = 0
7191
var endCalled = 0
72-
7392
var shouldBeUpdated = Set<String>()
74-
7593
var downloadedPreview = Set<String>()
7694
var downloaded = Set<String>()
95+
var downloadedOrder = [String]()
96+
var downloadedPreviewOrder = [String]()
7797
var removed = Set<String>()
7898

7999
var existingKeys = Array<K>()
@@ -131,18 +151,24 @@ class TestProcessor: OneWaySynchronizerProcessor {
131151
func owsDownloadItemPreview(forDescription description: OneWaySynchronizerItemDescription, completion: @escaping OwsSimpleCompletion) {
132152
objc_sync_enter(self); defer { objc_sync_exit(self) }
133153
downloadedPreview.insert(description.owsPrimaryKey)
154+
downloadedPreviewOrder.append(description.owsPrimaryKey)
134155
completion(nil)
135156
}
136157

137158
func owsDownloadItem(forDescription description: OneWaySynchronizerItemDescription, completion: @escaping OwsSimpleCompletion) {
138159
objc_sync_enter(self); defer { objc_sync_exit(self) }
139160
downloaded.insert(description.owsPrimaryKey)
161+
downloadedOrder.append(description.owsPrimaryKey)
140162
if !existingKeys.contains(description.owsPrimaryKey) {
141163
existingKeys.append(description.owsPrimaryKey)
142164
}
143165
completion((description as! TestItem).downloadError)
144166
}
145167

168+
func owsPrepareDownload(of descriptions: [OneWaySynchronizerItemDescription], completion: @escaping OwsItemsCompletion) {
169+
completion(nil, descriptions)
170+
}
171+
146172
}
147173

148174
class OneWaySynchronizerDemoTests: XCTestCase {
@@ -165,8 +191,9 @@ class OneWaySynchronizerDemoTests: XCTestCase {
165191
let expectation = XCTestExpectation(description: "sync")
166192
var failed: [Error]?
167193
let processor = TestProcessor(fetchList:[
168-
TestItem(key: "A"),
169-
TestItem(key: "B")
194+
TestItem(key: "A", order: 1),
195+
TestItem(key: "B", order: 0),
196+
TestItem(key: "C", order: 2)
170197
])
171198
let service = OneWaySynchronizer(processor: processor)
172199
service.concurrency = 1
@@ -194,6 +221,7 @@ class OneWaySynchronizerDemoTests: XCTestCase {
194221
XCTAssert(processor.endCalled == 1)
195222
XCTAssert(failed == nil)
196223
XCTAssert(Set(processor.fetchList.map({$0.owsPrimaryKey})) == processor.downloaded)
224+
XCTAssert(processor.downloadedOrder == ["B", "A", "C"])
197225
XCTAssert(processor.removeItemsCalled == 0)
198226
XCTAssert(processor.shouldBeUpdatedCalled == 0)
199227
XCTAssert(processor.removed.count == 0)
@@ -205,8 +233,9 @@ class OneWaySynchronizerDemoTests: XCTestCase {
205233
let expectation = XCTestExpectation(description: "sync")
206234
var failed: [Error]?
207235
let processor = TestProcessor(fetchList:[
208-
TestItem(key: "A"),
209-
TestItem(key: "B")
236+
TestItem(key: "A", order: 1),
237+
TestItem(key: "B", order: 0),
238+
TestItem(key: "C", order: 2)
210239
])
211240
let service = OneWaySynchronizer(processor: processor)
212241
service.concurrency = 1
@@ -219,10 +248,12 @@ class OneWaySynchronizerDemoTests: XCTestCase {
219248
wait(for: [expectation], timeout: 10)
220249
XCTAssert(failed == nil)
221250
XCTAssert(Set(processor.fetchList.map({$0.owsPrimaryKey})) == processor.downloaded)
251+
XCTAssert(processor.downloadedOrder == ["B", "A", "C"])
252+
XCTAssert(processor.downloadedPreviewOrder == ["B", "A", "C"])
222253
XCTAssert(processor.removeItemsCalled == 0)
223254
XCTAssert(processor.shouldBeUpdatedCalled == 0)
224255
XCTAssert(processor.removed.count == 0)
225-
XCTAssert(processor.downloadedPreview == Set(["A", "B"]))
256+
XCTAssert(processor.downloadedPreview == Set(["A", "B", "C"]))
226257
}
227258

228259
func testSuccessOnlyWithPreview() {
@@ -277,6 +308,55 @@ class OneWaySynchronizerDemoTests: XCTestCase {
277308
XCTAssert(processor.downloadedPreview.count == 0)
278309
}
279310

311+
func testCancellation() {
312+
313+
let startExpectation = XCTestExpectation(description: "start")
314+
let endExpectation = XCTestExpectation(description: "start")
315+
316+
let expectation = XCTestExpectation(description: "sync")
317+
var failed: [Error]?
318+
let processor = TestProcessor(fetchList:[
319+
TestItem(key: "A", order: 1),
320+
TestItem(key: "B", order: 0),
321+
TestItem(key: "C", order: 2)
322+
])
323+
let service = OneWaySynchronizer(processor: processor)
324+
service.concurrency = 1
325+
let localObserver = NotificationCenter.default.addObserver(forName: .OneWaySynchronizerDidChangeSyncStatusNotification, object: service, queue: OperationQueue.main) { (notification) in
326+
XCTAssert(Thread.isMainThread)
327+
if (notification.object as! OneWaySynchronizer).isSyncing {
328+
startExpectation.fulfill()
329+
}
330+
else {
331+
endExpectation.fulfill()
332+
}
333+
}
334+
335+
service.sync { (error) in
336+
failed = error
337+
expectation.fulfill()
338+
}
339+
340+
service.cancel() // cancel ASAP
341+
342+
wait(for: [expectation], timeout: 10)
343+
wait(for: [startExpectation, endExpectation], timeout: 10)
344+
345+
NotificationCenter.default.removeObserver(localObserver)
346+
347+
XCTAssert(processor.beginCalled == 1)
348+
XCTAssert(processor.endCalled == 1)
349+
XCTAssert(failed != nil)
350+
XCTAssert(failed!.count == 1)
351+
XCTAssert(isCancelError(failed![0]))
352+
XCTAssert(processor.downloaded.count == 0)
353+
XCTAssert(processor.downloadedOrder.count == 0)
354+
XCTAssert(processor.removeItemsCalled == 0)
355+
XCTAssert(processor.shouldBeUpdatedCalled == 0)
356+
XCTAssert(processor.removed.count == 0)
357+
XCTAssert(processor.downloadedPreview.count == 0)
358+
}
359+
280360
func testFetchFailure() {
281361

282362
let expectation = XCTestExpectation(description: "sync")

‎Demo/swiftlint.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
disabled_rules:
2+
- line_length
3+
- file_length
4+
- type_body_length
5+
- identifier_name

‎OneWaySynchronizer.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22

33
s.name = "OneWaySynchronizer"
4-
s.version = "1.0.0"
4+
s.version = "1.1.0"
55
s.summary = "OneWaySynchronizer - the simplest way to sync data from remote host into local storage."
66

77
s.homepage = "https://github.com/ladeiko/OneWaySynchronizer"
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Please sign in to comment.