@onekeyfe/react-native-range-downloader 3.0.81-alpha.1 → 3.0.81-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReactNativeRangeDownloader.podspec +1 -2
- package/android/build.gradle +0 -1
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveRules.kt +12 -5
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactOrphanSweep.kt +111 -0
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactStore.kt +194 -214
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/ReactNativeRangeDownloader.kt +21 -21
- package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveRulesTest.kt +39 -0
- package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactDeadlineTest.kt +26 -0
- package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactOrphanSweepTest.kt +107 -0
- package/ios/FirmwareArtifactStore.swift +667 -435
- package/ios/RangeDownloadLogic.swift +317 -0
- package/ios/ReactNativeRangeDownloader.swift +60 -484
- package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts +4 -7
- package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JFirmwareArchiveMaterializeParams.hpp +7 -6
- package/nitrogen/generated/android/c++/JFirmwareArtifactDownloadParams.hpp +7 -7
- package/nitrogen/generated/android/c++/JFirmwareArtifactReceipt.hpp +7 -3
- package/nitrogen/generated/android/c++/JHybridReactNativeRangeDownloaderSpec.cpp +0 -19
- package/nitrogen/generated/android/c++/JHybridReactNativeRangeDownloaderSpec.hpp +0 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveMaterializeParams.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactDownloadParams.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactReceipt.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/HybridReactNativeRangeDownloaderSpec.kt +0 -4
- package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Bridge.hpp +15 -0
- package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Umbrella.hpp +0 -3
- package/nitrogen/generated/ios/c++/HybridReactNativeRangeDownloaderSpecSwift.hpp +0 -11
- package/nitrogen/generated/ios/swift/FirmwareArchiveMaterializeParams.swift +32 -13
- package/nitrogen/generated/ios/swift/FirmwareArtifactDownloadParams.swift +39 -8
- package/nitrogen/generated/ios/swift/FirmwareArtifactReceipt.swift +13 -2
- package/nitrogen/generated/ios/swift/HybridReactNativeRangeDownloaderSpec.swift +0 -1
- package/nitrogen/generated/ios/swift/HybridReactNativeRangeDownloaderSpec_cxx.swift +0 -19
- package/nitrogen/generated/shared/c++/FirmwareArchiveMaterializeParams.hpp +6 -5
- package/nitrogen/generated/shared/c++/FirmwareArtifactDownloadParams.hpp +9 -9
- package/nitrogen/generated/shared/c++/FirmwareArtifactReceipt.hpp +6 -2
- package/nitrogen/generated/shared/c++/HybridReactNativeRangeDownloaderSpec.cpp +0 -1
- package/nitrogen/generated/shared/c++/HybridReactNativeRangeDownloaderSpec.hpp +0 -4
- package/package.json +1 -2
- package/src/ReactNativeRangeDownloader.nitro.ts +7 -11
- package/ios/FirmwareBackgroundSessionEventRouter.swift +0 -17
- package/nitrogen/generated/android/c++/JFirmwareArtifactLeaseReconcileParams.hpp +0 -76
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactLeaseReconcileParams.kt +0 -38
- package/nitrogen/generated/ios/swift/FirmwareArtifactLeaseReconcileParams.swift +0 -48
- package/nitrogen/generated/shared/c++/FirmwareArtifactLeaseReconcileParams.hpp +0 -76
|
@@ -9,6 +9,9 @@ import java.io.File
|
|
|
9
9
|
import java.security.MessageDigest
|
|
10
10
|
import java.util.concurrent.CopyOnWriteArrayList
|
|
11
11
|
import java.util.concurrent.atomic.AtomicLong
|
|
12
|
+
import kotlinx.coroutines.CoroutineScope
|
|
13
|
+
import kotlinx.coroutines.Dispatchers
|
|
14
|
+
import kotlinx.coroutines.SupervisorJob
|
|
12
15
|
|
|
13
16
|
// P1: Nitro adapter for the Android concurrent multi-range downloader.
|
|
14
17
|
//
|
|
@@ -34,6 +37,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
34
37
|
|
|
35
38
|
private val listeners = CopyOnWriteArrayList<Listener>()
|
|
36
39
|
private val nextListenerId = AtomicLong(1)
|
|
40
|
+
private val firmwareArtifactScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
|
37
41
|
|
|
38
42
|
// Active downloads keyed by "channel|taskId" so cancel/discardArtifacts can
|
|
39
43
|
// flip the abort flag + stop the worker pool BEFORE deleting files, instead of
|
|
@@ -268,8 +272,8 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
268
272
|
|
|
269
273
|
override fun getFirmwareArtifactCapabilities(): FirmwareArtifactCapabilities {
|
|
270
274
|
return FirmwareArtifactCapabilities(
|
|
271
|
-
firmwareArtifactProtocolVersion =
|
|
272
|
-
supportedRouteTypes = arrayOf("domain"
|
|
275
|
+
firmwareArtifactProtocolVersion = 4.0,
|
|
276
|
+
supportedRouteTypes = arrayOf("domain"),
|
|
273
277
|
supportsArchiveMaterialization = true,
|
|
274
278
|
maxReadBytes = FirmwareArtifactStore.MAX_READ_BYTES.toDouble(),
|
|
275
279
|
)
|
|
@@ -278,12 +282,13 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
278
282
|
override fun downloadFirmwareArtifact(
|
|
279
283
|
params: FirmwareArtifactDownloadParams,
|
|
280
284
|
): Promise<FirmwareArtifactReceipt> {
|
|
281
|
-
return Promise.async {
|
|
285
|
+
return Promise.async(firmwareArtifactScope) {
|
|
282
286
|
val artifact = FirmwareArtifactStore.download(params)
|
|
283
287
|
FirmwareArtifactReceipt(
|
|
284
288
|
artifactRef = artifact.artifactRef,
|
|
285
289
|
size = artifact.size.toDouble(),
|
|
286
290
|
sha256 = artifact.sha256,
|
|
291
|
+
expectedSha256Verified = params.expectedSha256 != null,
|
|
287
292
|
)
|
|
288
293
|
}
|
|
289
294
|
}
|
|
@@ -291,7 +296,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
291
296
|
override fun cancelFirmwareArtifactDownloads(
|
|
292
297
|
params: FirmwareArtifactCancelParams,
|
|
293
298
|
): Promise<Unit> {
|
|
294
|
-
return Promise.async {
|
|
299
|
+
return Promise.async(firmwareArtifactScope) {
|
|
295
300
|
FirmwareArtifactStore.cancelDownloads(params.transactionId)
|
|
296
301
|
}
|
|
297
302
|
}
|
|
@@ -299,7 +304,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
299
304
|
override fun discardFirmwareArtifact(
|
|
300
305
|
params: FirmwareArtifactRefParams,
|
|
301
306
|
): Promise<Unit> {
|
|
302
|
-
return Promise.async {
|
|
307
|
+
return Promise.async(firmwareArtifactScope) {
|
|
303
308
|
FirmwareArtifactStore.discard(params.artifactRef)
|
|
304
309
|
}
|
|
305
310
|
}
|
|
@@ -307,7 +312,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
307
312
|
override fun openFirmwareArtifact(
|
|
308
313
|
params: FirmwareArtifactRefParams,
|
|
309
314
|
): Promise<FirmwareArtifactReaderInfo> {
|
|
310
|
-
return Promise.async {
|
|
315
|
+
return Promise.async(firmwareArtifactScope) {
|
|
311
316
|
val (readerId, size) = FirmwareArtifactStore.open(params.artifactRef)
|
|
312
317
|
FirmwareArtifactReaderInfo(readerId = readerId, size = size.toDouble())
|
|
313
318
|
}
|
|
@@ -316,13 +321,15 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
316
321
|
override fun readFirmwareArtifact(
|
|
317
322
|
params: FirmwareArtifactReaderReadParams,
|
|
318
323
|
): Promise<ArrayBuffer> {
|
|
319
|
-
return Promise.async {
|
|
324
|
+
return Promise.async(firmwareArtifactScope) {
|
|
320
325
|
require(
|
|
321
326
|
params.offset.isFinite() &&
|
|
322
327
|
params.offset >= 0 &&
|
|
328
|
+
params.offset <= FirmwareArtifactStore.MAX_ARTIFACT_BYTES.toDouble() &&
|
|
323
329
|
params.offset.toLong().toDouble() == params.offset &&
|
|
324
330
|
params.length.isFinite() &&
|
|
325
331
|
params.length > 0 &&
|
|
332
|
+
params.length <= FirmwareArtifactStore.MAX_READ_BYTES.toDouble() &&
|
|
326
333
|
params.length.toInt().toDouble() == params.length
|
|
327
334
|
) {
|
|
328
335
|
"Invalid firmware artifact read"
|
|
@@ -340,7 +347,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
340
347
|
override fun closeFirmwareArtifact(
|
|
341
348
|
params: FirmwareArtifactReaderCloseParams,
|
|
342
349
|
): Promise<Unit> {
|
|
343
|
-
return Promise.async {
|
|
350
|
+
return Promise.async(firmwareArtifactScope) {
|
|
344
351
|
FirmwareArtifactStore.close(params.readerId)
|
|
345
352
|
}
|
|
346
353
|
}
|
|
@@ -348,7 +355,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
348
355
|
override fun materializeFirmwareArchive(
|
|
349
356
|
params: FirmwareArchiveMaterializeParams,
|
|
350
357
|
): Promise<FirmwareArchiveMaterializeResult> {
|
|
351
|
-
return Promise.async {
|
|
358
|
+
return Promise.async(firmwareArtifactScope) {
|
|
352
359
|
val artifacts = FirmwareArtifactStore.materializeArchive(
|
|
353
360
|
params.leaseRef,
|
|
354
361
|
params.archiveArtifactRef,
|
|
@@ -362,6 +369,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
362
369
|
artifactRef = entry.artifact.artifactRef,
|
|
363
370
|
size = entry.artifact.size.toDouble(),
|
|
364
371
|
sha256 = entry.artifact.sha256,
|
|
372
|
+
expectedSha256Verified = params.expectedEntries != null,
|
|
365
373
|
),
|
|
366
374
|
)
|
|
367
375
|
}.toTypedArray(),
|
|
@@ -372,7 +380,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
372
380
|
override fun createFirmwareArtifactLease(
|
|
373
381
|
params: FirmwareArtifactLeaseCreateParams,
|
|
374
382
|
): Promise<FirmwareArtifactLease> {
|
|
375
|
-
return Promise.async {
|
|
383
|
+
return Promise.async(firmwareArtifactScope) {
|
|
376
384
|
FirmwareArtifactLease(
|
|
377
385
|
leaseRef = FirmwareArtifactStore.createLease(params.transactionId),
|
|
378
386
|
)
|
|
@@ -382,7 +390,7 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
382
390
|
override fun retainFirmwareArtifact(
|
|
383
391
|
params: FirmwareArtifactLeaseRetainParams,
|
|
384
392
|
): Promise<Unit> {
|
|
385
|
-
return Promise.async {
|
|
393
|
+
return Promise.async(firmwareArtifactScope) {
|
|
386
394
|
FirmwareArtifactStore.retain(params.leaseRef, params.artifactRef)
|
|
387
395
|
}
|
|
388
396
|
}
|
|
@@ -390,21 +398,13 @@ class ReactNativeRangeDownloader : HybridReactNativeRangeDownloaderSpec() {
|
|
|
390
398
|
override fun releaseFirmwareArtifactLease(
|
|
391
399
|
params: FirmwareArtifactLeaseReleaseParams,
|
|
392
400
|
): Promise<Unit> {
|
|
393
|
-
return Promise.async {
|
|
401
|
+
return Promise.async(firmwareArtifactScope) {
|
|
394
402
|
FirmwareArtifactStore.releaseLease(params.leaseRef, params.disposition)
|
|
395
403
|
}
|
|
396
404
|
}
|
|
397
405
|
|
|
398
|
-
override fun reconcileFirmwareArtifactLeases(
|
|
399
|
-
params: FirmwareArtifactLeaseReconcileParams,
|
|
400
|
-
): Promise<Unit> {
|
|
401
|
-
return Promise.async {
|
|
402
|
-
FirmwareArtifactStore.reconcileLeases(params.activeLeaseRefs)
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
406
|
override fun sweepFirmwareArtifactOrphans(): Promise<FirmwareArtifactSweepResult> {
|
|
407
|
-
return Promise.async {
|
|
407
|
+
return Promise.async(firmwareArtifactScope) {
|
|
408
408
|
val (deletedFiles, deletedBytes) = FirmwareArtifactStore.sweepOrphans()
|
|
409
409
|
FirmwareArtifactSweepResult(
|
|
410
410
|
deletedFiles = deletedFiles.toDouble(),
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
package com.margelo.nitro.reactnativerangedownloader
|
|
2
2
|
|
|
3
|
+
import java.io.File
|
|
4
|
+
import java.io.FileOutputStream
|
|
5
|
+
import java.util.zip.ZipEntry
|
|
6
|
+
import java.util.zip.ZipOutputStream
|
|
3
7
|
import org.junit.Assert.assertEquals
|
|
4
8
|
import org.junit.Assert.assertThrows
|
|
9
|
+
import org.junit.Rule
|
|
5
10
|
import org.junit.Test
|
|
11
|
+
import org.junit.rules.TemporaryFolder
|
|
6
12
|
|
|
7
13
|
class FirmwareArchiveRulesTest {
|
|
14
|
+
@get:Rule
|
|
15
|
+
val temporaryFolder = TemporaryFolder()
|
|
16
|
+
|
|
8
17
|
private fun entry(
|
|
9
18
|
artifactId: String = "resource-entry",
|
|
10
19
|
entryName: String = "assets/icon.png",
|
|
@@ -72,4 +81,34 @@ class FirmwareArchiveRulesTest {
|
|
|
72
81
|
)
|
|
73
82
|
}
|
|
74
83
|
}
|
|
84
|
+
|
|
85
|
+
@Test
|
|
86
|
+
fun acceptsPortableEntriesWithoutExpectedIntegrityMetadata() {
|
|
87
|
+
val archive = createArchive("assets/icon.png", byteArrayOf(1, 2, 3))
|
|
88
|
+
|
|
89
|
+
val entries = FirmwareArchiveRules.validateCentralDirectory(archive, null)
|
|
90
|
+
|
|
91
|
+
assertEquals(1, entries.size)
|
|
92
|
+
assertEquals("assets/icon.png", entries.single().name)
|
|
93
|
+
assertEquals(3, entries.single().uncompressedSize)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@Test
|
|
97
|
+
fun rejectsTraversalWithoutExpectedIntegrityMetadata() {
|
|
98
|
+
val archive = createArchive("../icon.png", byteArrayOf(1))
|
|
99
|
+
|
|
100
|
+
assertThrows(IllegalArgumentException::class.java) {
|
|
101
|
+
FirmwareArchiveRules.validateCentralDirectory(archive, null)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private fun createArchive(entryName: String, content: ByteArray): File {
|
|
106
|
+
val archive = temporaryFolder.newFile("firmware.zip")
|
|
107
|
+
ZipOutputStream(FileOutputStream(archive)).use { zip ->
|
|
108
|
+
zip.putNextEntry(ZipEntry(entryName))
|
|
109
|
+
zip.write(content)
|
|
110
|
+
zip.closeEntry()
|
|
111
|
+
}
|
|
112
|
+
return archive
|
|
113
|
+
}
|
|
75
114
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.margelo.nitro.reactnativerangedownloader
|
|
2
|
+
|
|
3
|
+
import org.junit.Assert.assertEquals
|
|
4
|
+
import org.junit.Assert.assertThrows
|
|
5
|
+
import org.junit.Test
|
|
6
|
+
|
|
7
|
+
class FirmwareArtifactDeadlineTest {
|
|
8
|
+
@Test
|
|
9
|
+
fun defaultsToABoundedThreeMinuteDeadline() {
|
|
10
|
+
assertEquals(180.0, validateFirmwareDownloadDeadlineSeconds(null), 0.0)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@Test
|
|
14
|
+
fun preservesFractionalDeadlines() {
|
|
15
|
+
assertEquals(2.75, validateFirmwareDownloadDeadlineSeconds(2.75), 0.0)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Test
|
|
19
|
+
fun rejectsUnboundedOrInvalidDeadlines() {
|
|
20
|
+
listOf(0.0, -1.0, Double.NaN, Double.POSITIVE_INFINITY, 86_400.1).forEach {
|
|
21
|
+
assertThrows(IllegalArgumentException::class.java) {
|
|
22
|
+
validateFirmwareDownloadDeadlineSeconds(it)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
package com.margelo.nitro.reactnativerangedownloader
|
|
2
|
+
|
|
3
|
+
import java.io.File
|
|
4
|
+
import org.junit.Assert.assertEquals
|
|
5
|
+
import org.junit.Assert.assertFalse
|
|
6
|
+
import org.junit.Assert.assertTrue
|
|
7
|
+
import org.junit.Rule
|
|
8
|
+
import org.junit.Test
|
|
9
|
+
import org.junit.rules.TemporaryFolder
|
|
10
|
+
|
|
11
|
+
class FirmwareArtifactOrphanSweepTest {
|
|
12
|
+
@get:Rule
|
|
13
|
+
val temporaryFolder = TemporaryFolder()
|
|
14
|
+
|
|
15
|
+
@Test
|
|
16
|
+
fun removesOnlyStaleRootScratchEntriesWithExactNamesAndTypes() {
|
|
17
|
+
val root = temporaryFolder.newFolder("firmware-artifact-sweep")
|
|
18
|
+
val nowMs = 2_000_000_000_000L
|
|
19
|
+
val staleAt = nowMs - FIRMWARE_ARTIFACT_SCRATCH_GRACE_MS - 1
|
|
20
|
+
val freshAt = nowMs - FIRMWARE_ARTIFACT_SCRATCH_GRACE_MS + 1
|
|
21
|
+
val staleArchive = File(
|
|
22
|
+
root,
|
|
23
|
+
"archive-00000000-0000-4000-8000-000000000001",
|
|
24
|
+
).apply {
|
|
25
|
+
assertTrue(mkdirs())
|
|
26
|
+
File(this, "0.entry").writeText("archive")
|
|
27
|
+
}
|
|
28
|
+
val stalePromote = File(
|
|
29
|
+
root,
|
|
30
|
+
".promote-00000000-0000-4000-8000-000000000002",
|
|
31
|
+
).apply { writeText("promote") }
|
|
32
|
+
val freshArchive = File(
|
|
33
|
+
root,
|
|
34
|
+
"archive-00000000-0000-4000-8000-000000000003",
|
|
35
|
+
).apply { assertTrue(mkdirs()) }
|
|
36
|
+
val freshPromote = File(
|
|
37
|
+
root,
|
|
38
|
+
".promote-00000000-0000-4000-8000-000000000004",
|
|
39
|
+
).apply { writeText("promote") }
|
|
40
|
+
val malformedArchive = File(
|
|
41
|
+
root,
|
|
42
|
+
"archive-00000000-0000-4000-8000-000000000005.extra",
|
|
43
|
+
).apply { assertTrue(mkdirs()) }
|
|
44
|
+
val malformedPromote = File(
|
|
45
|
+
root,
|
|
46
|
+
".promote-00000000-0000-4000-8000-000000000006.tmp",
|
|
47
|
+
).apply { writeText("promote") }
|
|
48
|
+
val archiveNamedFile = File(
|
|
49
|
+
root,
|
|
50
|
+
"archive-00000000-0000-4000-8000-000000000007",
|
|
51
|
+
).apply { writeText("promote") }
|
|
52
|
+
val promoteNamedDirectory = File(
|
|
53
|
+
root,
|
|
54
|
+
".promote-00000000-0000-4000-8000-000000000008",
|
|
55
|
+
).apply { assertTrue(mkdirs()) }
|
|
56
|
+
val nestedArchive = File(
|
|
57
|
+
File(root, "nested"),
|
|
58
|
+
"archive-00000000-0000-4000-8000-000000000009",
|
|
59
|
+
).apply { assertTrue(mkdirs()) }
|
|
60
|
+
|
|
61
|
+
for (
|
|
62
|
+
entry in listOf(
|
|
63
|
+
staleArchive,
|
|
64
|
+
stalePromote,
|
|
65
|
+
malformedArchive,
|
|
66
|
+
malformedPromote,
|
|
67
|
+
archiveNamedFile,
|
|
68
|
+
promoteNamedDirectory,
|
|
69
|
+
nestedArchive,
|
|
70
|
+
)
|
|
71
|
+
) {
|
|
72
|
+
assertTrue(entry.setLastModified(staleAt))
|
|
73
|
+
}
|
|
74
|
+
for (entry in listOf(freshArchive, freshPromote)) {
|
|
75
|
+
assertTrue(entry.setLastModified(freshAt))
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
val result = sweepFirmwareArtifactOrphansAtRoot(
|
|
79
|
+
root = root,
|
|
80
|
+
retainedSha256 = emptySet(),
|
|
81
|
+
activeSha256 = emptySet(),
|
|
82
|
+
openPaths = emptySet(),
|
|
83
|
+
nowMs = nowMs,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
assertEquals(2, result.first)
|
|
87
|
+
assertEquals(14L, result.second)
|
|
88
|
+
assertFalse(staleArchive.exists())
|
|
89
|
+
assertFalse(stalePromote.exists())
|
|
90
|
+
for (
|
|
91
|
+
retainedEntry in listOf(
|
|
92
|
+
freshArchive,
|
|
93
|
+
freshPromote,
|
|
94
|
+
malformedArchive,
|
|
95
|
+
malformedPromote,
|
|
96
|
+
archiveNamedFile,
|
|
97
|
+
promoteNamedDirectory,
|
|
98
|
+
nestedArchive,
|
|
99
|
+
)
|
|
100
|
+
) {
|
|
101
|
+
assertTrue(
|
|
102
|
+
"Unexpectedly removed ${retainedEntry.name}",
|
|
103
|
+
retainedEntry.exists(),
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|