Skip to content

Commit 4a93798

Browse files
authored
test(Storage): Add progress listener integ tests (#1152)
1 parent 1a1aa07 commit 4a93798

File tree

9 files changed

+187
-6
lines changed

9 files changed

+187
-6
lines changed

AmplifyPlugins/API/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,4 @@ SPEC CHECKSUMS:
108108

109109
PODFILE CHECKSUM: 857e4ea8246683593b8a7db77014aeb7340c15a5
110110

111-
COCOAPODS: 1.9.3
111+
COCOAPODS: 1.10.1

AmplifyPlugins/Analytics/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,4 @@ SPEC CHECKSUMS:
104104

105105
PODFILE CHECKSUM: 48d1574dddce5cef7bdb7b05b06fc588ee22956e
106106

107-
COCOAPODS: 1.9.3
107+
COCOAPODS: 1.10.1

AmplifyPlugins/Auth/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,4 @@ SPEC CHECKSUMS:
8989

9090
PODFILE CHECKSUM: 371cf67fe35ebb5167d0880bad12b01618a0fb0e
9191

92-
COCOAPODS: 1.9.3
92+
COCOAPODS: 1.10.1

AmplifyPlugins/DataStore/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,4 @@ SPEC CHECKSUMS:
118118

119119
PODFILE CHECKSUM: 04860e414d616b67d24ed3346a60700f427764b9
120120

121-
COCOAPODS: 1.9.3
121+
COCOAPODS: 1.10.1

AmplifyPlugins/Predictions/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,4 @@ SPEC CHECKSUMS:
129129

130130
PODFILE CHECKSUM: 65cca76c6059f8ccc8628936971fb9e4b035fb10
131131

132-
COCOAPODS: 1.9.3
132+
COCOAPODS: 1.10.1
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
amplify
2+
amplify/\#current-cloud-backend
3+
amplify/.config/local-*
4+
amplify/logs
5+
amplify/mock-data
6+
amplify/backend/amplify-meta.json
7+
amplify/backend/awscloudformation
8+
amplify/backend/.temp
9+
build/
10+
dist/
11+
node_modules/
12+
aws-exports.js
13+
awsconfiguration.json
14+
amplifyconfiguration.json
15+
amplify-build-config.json
16+
amplify-gradle-config.json
17+
amplifytools.xcconfig
18+
.secret-*
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Combine
9+
import XCTest
10+
import Amplify
11+
12+
@testable import AmplifyTestCommon
13+
14+
/// Tests asserting that Storage Operations dispatch progress updates via various flavors of the API.
15+
///
16+
/// These tests are useful to play around with the different thresholds for progress notifications.
17+
/// You will always receive a completion notification as long as the upload completes, even if you
18+
/// attach the result listener after the upload has completed.
19+
///
20+
/// However, if you attach a **progress** listener to an operation that has already completed,
21+
/// you will not receive a value from that publisher.
22+
/// is no guarantee at what threshold you will receive more granular updates, since this is controlled
23+
/// by the OS.
24+
///
25+
/// On my laptop, on my network, I only get "progress: 1.0" notifications for payloads
26+
/// of ~0-1MB. After ~1 MB, I start getting notified more frequently.
27+
class AWSS3StoragePluginProgressTests: AWSS3StoragePluginTestBase {
28+
29+
func testUploadProgressViaListener() {
30+
let timestamp = String(Date().timeIntervalSince1970)
31+
let key = "testUploadProgressViaListener-\(timestamp)"
32+
33+
addTeardownBlock {
34+
self.removeTestFile(withKey: key)
35+
}
36+
37+
let resultReceived = expectation(description: "resultReceived")
38+
let progressReceived = expectation(description: "progressReceived")
39+
progressReceived.assertForOverFulfill = false
40+
_ = Amplify.Storage.uploadData(
41+
key: key,
42+
data: .testDataOfSize(.bytes(100)),
43+
progressListener: { progress in
44+
progressReceived.fulfill()
45+
print("Progress: \(progress.fractionCompleted)")
46+
}, resultListener: { result in
47+
resultReceived.fulfill()
48+
print("Result received: \(result)")
49+
}
50+
)
51+
52+
waitForExpectations(timeout: TestCommonConstants.networkTimeout)
53+
}
54+
55+
func testUploadProgressViaPublisher() {
56+
var cancellables = Set<AnyCancellable>()
57+
58+
let timestamp = String(Date().timeIntervalSince1970)
59+
let key = "testUploadProgressViaPublisher-\(timestamp)"
60+
61+
addTeardownBlock {
62+
self.removeTestFile(withKey: key)
63+
}
64+
65+
let completionReceived = expectation(description: "resultReceived")
66+
let progressReceived = expectation(description: "progressReceived")
67+
progressReceived.assertForOverFulfill = false
68+
let uploadOperation = Amplify.Storage.uploadData(
69+
key: key,
70+
data: .testDataOfSize(.bytes(100)))
71+
72+
uploadOperation.resultPublisher
73+
.sink(receiveCompletion: { completion in
74+
completionReceived.fulfill()
75+
print("Completion received: \(completion)")
76+
}, receiveValue: { _ in })
77+
.store(in: &cancellables)
78+
79+
uploadOperation.progressPublisher
80+
.sink { progress in
81+
progressReceived.fulfill()
82+
print("Progress: \(progress.fractionCompleted)")
83+
}
84+
.store(in: &cancellables)
85+
86+
waitForExpectations(timeout: TestCommonConstants.networkTimeout)
87+
}
88+
89+
func testPublisherDeliveryAfterUploadCompletes() {
90+
var cancellables = Set<AnyCancellable>()
91+
92+
let timestamp = String(Date().timeIntervalSince1970)
93+
let key = "testUploadProgressDeliveryAfterCompletion-\(timestamp)"
94+
95+
addTeardownBlock {
96+
self.removeTestFile(withKey: key)
97+
}
98+
99+
// Wait for the upload to complete
100+
let uploadComplete = expectation(description: "uploadComplete")
101+
let uploadOperation = Amplify.Storage.uploadData(
102+
key: key,
103+
data: .testDataOfSize(.bytes(100)),
104+
resultListener: { _ in uploadComplete.fulfill() }
105+
)
106+
wait(for: [uploadComplete], timeout: TestCommonConstants.networkTimeout)
107+
108+
// Result publisher should immediately complete, and should deliver a value
109+
let resultCompletionReceived = expectation(description: "resultCompletionReceived")
110+
let resultValueReceived = expectation(description: "resultValueReceived")
111+
uploadOperation.resultPublisher
112+
.sink(
113+
receiveCompletion: { _ in resultCompletionReceived.fulfill() },
114+
receiveValue: { _ in resultValueReceived.fulfill() }
115+
)
116+
.store(in: &cancellables)
117+
waitForExpectations(timeout: 0.5)
118+
119+
// Progress listener should immediately complete without delivering a value
120+
let progressValueReceived = expectation(description: "progressValueReceived")
121+
progressValueReceived.isInverted = true
122+
let progressCompletionReceived = expectation(description: "progressCompletionReceived")
123+
uploadOperation.progressPublisher
124+
.sink(
125+
receiveCompletion: { _ in progressCompletionReceived.fulfill() },
126+
receiveValue: { _ in progressValueReceived.fulfill() }
127+
)
128+
.store(in: &cancellables)
129+
waitForExpectations(timeout: 0.5)
130+
}
131+
132+
// MARK: - Utilities
133+
134+
private func removeTestFile(withKey key: String) {
135+
// Never do this in prod
136+
let semaphore = DispatchSemaphore(value: 0)
137+
_ = Amplify.Storage.remove(key: key) { _ in semaphore.signal() }
138+
semaphore.wait()
139+
}
140+
}
141+
142+
private extension Data {
143+
static func testDataOfSize(_ size: Int) -> Data {
144+
Data(repeating: 0xff, count: size)
145+
}
146+
}
147+
148+
private extension Int {
149+
static func bytes(_ size: Int) -> Int { return size }
150+
151+
static func kilobytes(_ size: Int) -> Int { return size * 1_024 }
152+
static func kilobytes(_ size: Float) -> Int { return Int(size * 1_024) }
153+
154+
static func megabytes(_ size: Int) -> Int { return size * 1_024 * 1_024 }
155+
static func megabytes(_ size: Float) -> Int { return Int(size * 1_024 * 1_024) }
156+
157+
static func gigabytes(_ size: Int) -> Int { return size * 1_024 * 1_024 * 1_024 }
158+
static func gigabytes(_ size: Float) -> Int { return Int(size * 1_024 * 1_024 * 1_024) }
159+
}

AmplifyPlugins/Storage/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,4 @@ SPEC CHECKSUMS:
104104

105105
PODFILE CHECKSUM: 23c3028505a2f56c001d01c66c1622dff6f8dd8e
106106

107-
COCOAPODS: 1.9.3
107+
COCOAPODS: 1.10.1

AmplifyPlugins/Storage/StoragePlugin.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
B4FEB6FE2375DA1600818CD2 /* AWSS3StorageServiceEscapeHatchBehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4FEB6D82375DA1500818CD2 /* AWSS3StorageServiceEscapeHatchBehaviorTests.swift */; };
111111
B4FEB6FF2375DA1600818CD2 /* AWSS3StorageServiceMultiPartUploadBehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4FEB6D92375DA1500818CD2 /* AWSS3StorageServiceMultiPartUploadBehaviorTests.swift */; };
112112
C7C8E0966435A67F3C443F6A /* Pods_AWSS3StoragePlugin_AWSS3StoragePluginTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A7357AE068121E124484319 /* Pods_AWSS3StoragePlugin_AWSS3StoragePluginTests.framework */; };
113+
FA106A3F261F9B2B00032EF8 /* AWSS3StoragePluginProgressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA106A3E261F9B2B00032EF8 /* AWSS3StoragePluginProgressTests.swift */; };
113114
FA11225C24944BEB00492048 /* AWSS3StoragePluginBaseConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA11225B24944BEB00492048 /* AWSS3StoragePluginBaseConfigTests.swift */; };
114115
FA1C820825868F46006160E9 /* AWSS3StoragePluginAmplifyVersionableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1C820725868F46006160E9 /* AWSS3StoragePluginAmplifyVersionableTests.swift */; };
115116
/* End PBXBuildFile section */
@@ -270,6 +271,7 @@
270271
E0B21A30E0704D952D3DE1C3 /* Pods-HostApp-AWSS3StoragePluginFunctionalTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HostApp-AWSS3StoragePluginFunctionalTests.debug.xcconfig"; path = "Target Support Files/Pods-HostApp-AWSS3StoragePluginFunctionalTests/Pods-HostApp-AWSS3StoragePluginFunctionalTests.debug.xcconfig"; sourceTree = "<group>"; };
271272
F2499EEE6F1A16D91ABBEC87 /* Pods-AWSPinpointAnalyticsPluginTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AWSPinpointAnalyticsPluginTests.debug.xcconfig"; path = "Target Support Files/Pods-AWSPinpointAnalyticsPluginTests/Pods-AWSPinpointAnalyticsPluginTests.debug.xcconfig"; sourceTree = "<group>"; };
272273
F899D288C85D558A4322DDB6 /* Pods-AWSS3StoragePlugin-AWSS3StoragePluginTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AWSS3StoragePlugin-AWSS3StoragePluginTests.release.xcconfig"; path = "Target Support Files/Pods-AWSS3StoragePlugin-AWSS3StoragePluginTests/Pods-AWSS3StoragePlugin-AWSS3StoragePluginTests.release.xcconfig"; sourceTree = "<group>"; };
274+
FA106A3E261F9B2B00032EF8 /* AWSS3StoragePluginProgressTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AWSS3StoragePluginProgressTests.swift; sourceTree = "<group>"; };
273275
FA11225B24944BEB00492048 /* AWSS3StoragePluginBaseConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AWSS3StoragePluginBaseConfigTests.swift; sourceTree = "<group>"; };
274276
FA1C820725868F46006160E9 /* AWSS3StoragePluginAmplifyVersionableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AWSS3StoragePluginAmplifyVersionableTests.swift; sourceTree = "<group>"; };
275277
/* End PBXFileReference section */
@@ -317,6 +319,7 @@
317319
children = (
318320
B4FEB7092375DA2200818CD2 /* AWSS3StoragePluginAccessLevelTests.swift */,
319321
B4FEB7082375DA2200818CD2 /* AWSS3StoragePluginBasicIntegrationTests.swift */,
322+
FA106A3E261F9B2B00032EF8 /* AWSS3StoragePluginProgressTests.swift */,
320323
B4FEB7042375DA2200818CD2 /* AWSS3StoragePluginConfigurationTests.swift */,
321324
B4FEB7072375DA2200818CD2 /* AWSS3StoragePluginNegativeTests.swift */,
322325
B4FEB7052375DA2200818CD2 /* AWSS3StoragePluginOptionsUsabilityTests.swift */,
@@ -1123,6 +1126,7 @@
11231126
2149E6C8238CA47500873955 /* AWSS3StoragePluginAccessLevelTests.swift in Sources */,
11241127
2149E6C5238CA46B00873955 /* AWSS3StoragePluginTestBase.swift in Sources */,
11251128
2139A2402390688300A9AC4D /* AWSS3StoragePluginPutDataResumabilityTests.swift in Sources */,
1129+
FA106A3F261F9B2B00032EF8 /* AWSS3StoragePluginProgressTests.swift in Sources */,
11261130
2139A2412390688600A9AC4D /* AWSS3StoragePluginUploadFileResumabilityTests.swift in Sources */,
11271131
2139A23E2390687B00A9AC4D /* AWSS3StoragePluginDownloadFileResumabilityTests.swift in Sources */,
11281132
2149E6C7238CA47500873955 /* AWSS3StoragePluginNegativeTests.swift in Sources */,

0 commit comments

Comments
 (0)