@onekeyfe/react-native-image 3.0.98
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/LICENSE +21 -0
- package/OneKeyImage.podspec +32 -0
- package/README.md +88 -0
- package/android/CMakeLists.txt +12 -0
- package/android/build.gradle +85 -0
- package/android/consumer-rules.pro +10 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImage.kt +616 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageCache.kt +131 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageDecodeDimensions.kt +169 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageGlideRegistry.kt +285 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageModel.kt +68 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImagePackage.kt +28 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageSafety.kt +1120 -0
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyTosUrl.kt +93 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyAnimationTimelineInspectorTest.kt +210 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyImageCacheTypeTest.kt +16 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyImageDecodeDimensionsTest.kt +70 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyImageModelTest.kt +65 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyImageRequestSignatureTest.kt +33 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyImageSafetyTest.kt +346 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyResourceCleanupTest.kt +43 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyTerminalEventPairTest.kt +38 -0
- package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyTosUrlTest.kt +82 -0
- package/ios/OneKeyImage.swift +636 -0
- package/ios/OneKeyImageCache.swift +215 -0
- package/ios/OneKeyImageRequestContext.swift +781 -0
- package/ios/OneKeyTosURL.swift +69 -0
- package/ios/tests/OneKeyImageInfrastructureTests.swift +555 -0
- package/ios/tests/OneKeyTosURLTests.swift +142 -0
- package/lib/module/OneKeyImage.nitro.js +30 -0
- package/lib/module/index.js +223 -0
- package/lib/module/package.json +1 -0
- package/lib/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
- package/lib/nitrogen/generated/android/c++/JFunc_void_double_double_OneKeyImageCacheType.hpp +77 -0
- package/lib/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageCacheSpec.cpp +130 -0
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageCacheSpec.hpp +66 -0
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.cpp +255 -0
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.hpp +93 -0
- package/lib/nitrogen/generated/android/c++/JOneKeyImageCachePolicy.hpp +64 -0
- package/lib/nitrogen/generated/android/c++/JOneKeyImageCacheType.hpp +61 -0
- package/lib/nitrogen/generated/android/c++/JOneKeyImageContentFit.hpp +64 -0
- package/lib/nitrogen/generated/android/c++/JOneKeyImageLoadingStrategy.hpp +61 -0
- package/lib/nitrogen/generated/android/c++/JOneKeyImagePreloadSource.hpp +88 -0
- package/lib/nitrogen/generated/android/c++/JOneKeyImageVariant.hpp +64 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.cpp +144 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.hpp +54 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/Func_void.kt +78 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/Func_void_double_double_OneKeyImageCacheType.kt +78 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/Func_void_std__string.kt +78 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageCacheSpec.kt +69 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt +189 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageCachePolicy.kt +25 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageCacheType.kt +24 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageContentFit.kt +25 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageLoadingStrategy.kt +24 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImagePreloadSource.kt +86 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageVariant.kt +25 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/onekeyimageOnLoad.kt +35 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyImageManager.kt +96 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyImageStateUpdater.kt +23 -0
- package/lib/nitrogen/generated/android/onekeyimage+autolinking.cmake +85 -0
- package/lib/nitrogen/generated/android/onekeyimage+autolinking.gradle +27 -0
- package/lib/nitrogen/generated/android/onekeyimageOnLoad.cpp +78 -0
- package/lib/nitrogen/generated/android/onekeyimageOnLoad.hpp +34 -0
- package/lib/nitrogen/generated/ios/OneKeyImage+autolinking.rb +62 -0
- package/lib/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.cpp +90 -0
- package/lib/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.hpp +405 -0
- package/lib/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Umbrella.hpp +71 -0
- package/lib/nitrogen/generated/ios/OneKeyImageAutolinking.mm +41 -0
- package/lib/nitrogen/generated/ios/OneKeyImageAutolinking.swift +38 -0
- package/lib/nitrogen/generated/ios/c++/HybridOneKeyImageCacheSpecSwift.cpp +11 -0
- package/lib/nitrogen/generated/ios/c++/HybridOneKeyImageCacheSpecSwift.hpp +114 -0
- package/lib/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.cpp +11 -0
- package/lib/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.hpp +206 -0
- package/lib/nitrogen/generated/ios/c++/views/HybridOneKeyImageComponent.mm +228 -0
- package/lib/nitrogen/generated/ios/swift/Func_void.swift +46 -0
- package/lib/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/lib/nitrogen/generated/ios/swift/Func_void_double_double_OneKeyImageCacheType.swift +46 -0
- package/lib/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/lib/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageCacheSpec.swift +58 -0
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageCacheSpec_cxx.swift +202 -0
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageSpec.swift +70 -0
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageSpec_cxx.swift +539 -0
- package/lib/nitrogen/generated/ios/swift/OneKeyImageCachePolicy.swift +48 -0
- package/lib/nitrogen/generated/ios/swift/OneKeyImageCacheType.swift +44 -0
- package/lib/nitrogen/generated/ios/swift/OneKeyImageContentFit.swift +48 -0
- package/lib/nitrogen/generated/ios/swift/OneKeyImageLoadingStrategy.swift +44 -0
- package/lib/nitrogen/generated/ios/swift/OneKeyImagePreloadSource.swift +148 -0
- package/lib/nitrogen/generated/ios/swift/OneKeyImageVariant.swift +48 -0
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageCacheSpec.cpp +24 -0
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageCacheSpec.hpp +68 -0
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.cpp +52 -0
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.hpp +108 -0
- package/lib/nitrogen/generated/shared/c++/OneKeyImageCachePolicy.hpp +84 -0
- package/lib/nitrogen/generated/shared/c++/OneKeyImageCacheType.hpp +80 -0
- package/lib/nitrogen/generated/shared/c++/OneKeyImageContentFit.hpp +84 -0
- package/lib/nitrogen/generated/shared/c++/OneKeyImageLoadingStrategy.hpp +80 -0
- package/lib/nitrogen/generated/shared/c++/OneKeyImagePreloadSource.hpp +114 -0
- package/lib/nitrogen/generated/shared/c++/OneKeyImageVariant.hpp +84 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.cpp +62 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.hpp +132 -0
- package/lib/nitrogen/generated/shared/json/OneKeyImageConfig.json +24 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/OneKeyImage.nitro.d.ts +67 -0
- package/lib/typescript/src/index.d.ts +55 -0
- package/nitro.json +31 -0
- package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_double_double_OneKeyImageCacheType.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
- package/nitrogen/generated/android/c++/JHybridOneKeyImageCacheSpec.cpp +130 -0
- package/nitrogen/generated/android/c++/JHybridOneKeyImageCacheSpec.hpp +66 -0
- package/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.cpp +255 -0
- package/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.hpp +93 -0
- package/nitrogen/generated/android/c++/JOneKeyImageCachePolicy.hpp +64 -0
- package/nitrogen/generated/android/c++/JOneKeyImageCacheType.hpp +61 -0
- package/nitrogen/generated/android/c++/JOneKeyImageContentFit.hpp +64 -0
- package/nitrogen/generated/android/c++/JOneKeyImageLoadingStrategy.hpp +61 -0
- package/nitrogen/generated/android/c++/JOneKeyImagePreloadSource.hpp +88 -0
- package/nitrogen/generated/android/c++/JOneKeyImageVariant.hpp +64 -0
- package/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.cpp +144 -0
- package/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.hpp +54 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/Func_void.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/Func_void_double_double_OneKeyImageCacheType.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/Func_void_std__string.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageCacheSpec.kt +69 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt +189 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageCachePolicy.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageCacheType.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageContentFit.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageLoadingStrategy.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImagePreloadSource.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/OneKeyImageVariant.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/onekeyimageOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyImageManager.kt +96 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyImageStateUpdater.kt +23 -0
- package/nitrogen/generated/android/onekeyimage+autolinking.cmake +85 -0
- package/nitrogen/generated/android/onekeyimage+autolinking.gradle +27 -0
- package/nitrogen/generated/android/onekeyimageOnLoad.cpp +78 -0
- package/nitrogen/generated/android/onekeyimageOnLoad.hpp +34 -0
- package/nitrogen/generated/ios/OneKeyImage+autolinking.rb +62 -0
- package/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.cpp +90 -0
- package/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.hpp +405 -0
- package/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Umbrella.hpp +71 -0
- package/nitrogen/generated/ios/OneKeyImageAutolinking.mm +41 -0
- package/nitrogen/generated/ios/OneKeyImageAutolinking.swift +38 -0
- package/nitrogen/generated/ios/c++/HybridOneKeyImageCacheSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridOneKeyImageCacheSpecSwift.hpp +114 -0
- package/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.hpp +206 -0
- package/nitrogen/generated/ios/c++/views/HybridOneKeyImageComponent.mm +228 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_double_double_OneKeyImageCacheType.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridOneKeyImageCacheSpec.swift +58 -0
- package/nitrogen/generated/ios/swift/HybridOneKeyImageCacheSpec_cxx.swift +202 -0
- package/nitrogen/generated/ios/swift/HybridOneKeyImageSpec.swift +70 -0
- package/nitrogen/generated/ios/swift/HybridOneKeyImageSpec_cxx.swift +539 -0
- package/nitrogen/generated/ios/swift/OneKeyImageCachePolicy.swift +48 -0
- package/nitrogen/generated/ios/swift/OneKeyImageCacheType.swift +44 -0
- package/nitrogen/generated/ios/swift/OneKeyImageContentFit.swift +48 -0
- package/nitrogen/generated/ios/swift/OneKeyImageLoadingStrategy.swift +44 -0
- package/nitrogen/generated/ios/swift/OneKeyImagePreloadSource.swift +148 -0
- package/nitrogen/generated/ios/swift/OneKeyImageVariant.swift +48 -0
- package/nitrogen/generated/shared/c++/HybridOneKeyImageCacheSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridOneKeyImageCacheSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.cpp +52 -0
- package/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.hpp +108 -0
- package/nitrogen/generated/shared/c++/OneKeyImageCachePolicy.hpp +84 -0
- package/nitrogen/generated/shared/c++/OneKeyImageCacheType.hpp +80 -0
- package/nitrogen/generated/shared/c++/OneKeyImageContentFit.hpp +84 -0
- package/nitrogen/generated/shared/c++/OneKeyImageLoadingStrategy.hpp +80 -0
- package/nitrogen/generated/shared/c++/OneKeyImagePreloadSource.hpp +114 -0
- package/nitrogen/generated/shared/c++/OneKeyImageVariant.hpp +84 -0
- package/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.cpp +62 -0
- package/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.hpp +132 -0
- package/nitrogen/generated/shared/json/OneKeyImageConfig.json +24 -0
- package/package.json +128 -0
- package/src/OneKeyImage.nitro.ts +86 -0
- package/src/index.tsx +376 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
package com.margelo.nitro.onekeyimage
|
|
2
|
+
|
|
3
|
+
import com.bumptech.glide.load.engine.GlideException
|
|
4
|
+
import com.bumptech.glide.signature.ObjectKey
|
|
5
|
+
import org.junit.Assert.assertEquals
|
|
6
|
+
import org.junit.Assert.assertFalse
|
|
7
|
+
import org.junit.Assert.assertNotEquals
|
|
8
|
+
import org.junit.Assert.assertThrows
|
|
9
|
+
import org.junit.Assert.assertTrue
|
|
10
|
+
import org.junit.Test
|
|
11
|
+
import java.io.ByteArrayInputStream
|
|
12
|
+
import java.io.ByteArrayOutputStream
|
|
13
|
+
import java.io.IOException
|
|
14
|
+
import java.security.MessageDigest
|
|
15
|
+
|
|
16
|
+
class OneKeyImageSafetyTest {
|
|
17
|
+
@Test
|
|
18
|
+
fun contentLengthAllowsBoundaryAndRejectsNextByte() {
|
|
19
|
+
OneKeyImageSafety.requireEncodedLength(OneKeyImageSafety.MAX_ENCODED_BYTES)
|
|
20
|
+
|
|
21
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
22
|
+
OneKeyImageSafety.requireEncodedLength(OneKeyImageSafety.MAX_ENCODED_BYTES + 1L)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Test
|
|
27
|
+
fun limitedStreamChecksActualReadBytes() {
|
|
28
|
+
val stream = OneKeyLimitedInputStream(
|
|
29
|
+
ByteArrayInputStream(ByteArray(6)),
|
|
30
|
+
maximumBytes = 4L,
|
|
31
|
+
)
|
|
32
|
+
val firstChunk = ByteArray(4)
|
|
33
|
+
|
|
34
|
+
assertEquals(4, stream.read(firstChunk))
|
|
35
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
36
|
+
stream.read()
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Test
|
|
41
|
+
fun limitedStreamCountsSkippedBytes() {
|
|
42
|
+
val stream = OneKeyLimitedInputStream(
|
|
43
|
+
ByteArrayInputStream(ByteArray(6)),
|
|
44
|
+
maximumBytes = 4L,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
assertEquals(4L, stream.skip(4L))
|
|
48
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
49
|
+
stream.skip(1L)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Test
|
|
54
|
+
fun dataUriByteCountHandlesPaddingWithoutDecoding() {
|
|
55
|
+
val padded = "data:image/png;base64,QUJDRA=="
|
|
56
|
+
val unpadded = "data:image/png;base64,QUJDRA"
|
|
57
|
+
|
|
58
|
+
assertEquals(4L, OneKeyImageSafety.dataUriDecodedByteCount(padded, padded.indexOf(',') + 1))
|
|
59
|
+
assertEquals(4L, OneKeyImageSafety.dataUriDecodedByteCount(unpadded, unpadded.indexOf(',') + 1))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@Test
|
|
63
|
+
fun dataUriRejectsEncodedTextThatCouldAllocateBeyondDecodedLimit() {
|
|
64
|
+
val maximumEncodedCharacters =
|
|
65
|
+
((OneKeyImageSafety.MAX_DATA_URI_DECODED_BYTES + 2L) / 3L * 4L).toInt()
|
|
66
|
+
val prefix = "data:image/png;base64,"
|
|
67
|
+
val oversized = prefix + "A".repeat(maximumEncodedCharacters + 1)
|
|
68
|
+
|
|
69
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
70
|
+
OneKeyImageSafety.dataUriDecodedByteCount(oversized, prefix.length)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@Test
|
|
75
|
+
fun staticDimensionGuardChecksPixelsAndSides() {
|
|
76
|
+
OneKeyImageSafety.requireStaticDimensions(10_000, 10_000)
|
|
77
|
+
|
|
78
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
79
|
+
OneKeyImageSafety.requireStaticDimensions(10_001, 10_000)
|
|
80
|
+
}
|
|
81
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
82
|
+
OneKeyImageSafety.requireStaticDimensions(32_769, 1)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@Test
|
|
87
|
+
fun animatedGuardsBoundTheUnavoidableCanvasAndFrameCount() {
|
|
88
|
+
OneKeyImageSafety.requireAnimatedDimensions(2048, 2048)
|
|
89
|
+
OneKeyImageSafety.requireAnimationFrameCount(1000)
|
|
90
|
+
|
|
91
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
92
|
+
OneKeyImageSafety.requireAnimatedDimensions(2049, 2048)
|
|
93
|
+
}
|
|
94
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
95
|
+
OneKeyImageSafety.requireAnimationFrameCount(1001)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Test
|
|
100
|
+
fun avifBrandIsRejectedFromFtypBox() {
|
|
101
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
102
|
+
OneKeyEncodedImageInspector.inspect(
|
|
103
|
+
ByteArrayInputStream(bmffBox("ftyp", ftypPayload("avif"))),
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
val nonAvif = OneKeyEncodedImageInspector.inspect(
|
|
108
|
+
ByteArrayInputStream(bmffBox("ftyp", ftypPayload("isom"))),
|
|
109
|
+
)
|
|
110
|
+
assertFalse(nonAvif.animated)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@Test
|
|
114
|
+
fun avifCannotHideBehindLeadingOrExtendedBmffBoxes() {
|
|
115
|
+
val leadingFree = bmffBox("free", byteArrayOf()) +
|
|
116
|
+
bmffBox("ftyp", ftypPayload("mif1", "avif"))
|
|
117
|
+
val leadingExtended = bmffBox("free", byteArrayOf(), extended = true) +
|
|
118
|
+
bmffBox("ftyp", ftypPayload("avis"))
|
|
119
|
+
val leadingUnknown = bmffBox("junk", byteArrayOf()) +
|
|
120
|
+
bmffBox("ftyp", ftypPayload("avif"))
|
|
121
|
+
|
|
122
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
123
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(leadingFree))
|
|
124
|
+
}
|
|
125
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
126
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(leadingExtended))
|
|
127
|
+
}
|
|
128
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
129
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(leadingUnknown))
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@Test
|
|
134
|
+
fun ambiguousOrOverlongBmffFailsClosed() {
|
|
135
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
136
|
+
OneKeyEncodedImageInspector.inspect(
|
|
137
|
+
ByteArrayInputStream(bmffBox("free", byteArrayOf())),
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
val overlong = ByteArrayOutputStream().apply {
|
|
141
|
+
writeIntBe(this, 300_000)
|
|
142
|
+
write("free".toByteArray())
|
|
143
|
+
}.toByteArray()
|
|
144
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
145
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(overlong))
|
|
146
|
+
}
|
|
147
|
+
val unknownOverlong = ByteArrayOutputStream().apply {
|
|
148
|
+
writeIntBe(this, 300_000)
|
|
149
|
+
write("junk".toByteArray())
|
|
150
|
+
}.toByteArray()
|
|
151
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
152
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(unknownOverlong))
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@Test
|
|
157
|
+
fun xmlAndSvgHeadersAreNotMisclassifiedAsBmff() {
|
|
158
|
+
val xml = OneKeyEncodedImageInspector.inspect(
|
|
159
|
+
ByteArrayInputStream("<?xml version=\"1.0\"?><svg/>".toByteArray()),
|
|
160
|
+
)
|
|
161
|
+
val svg = OneKeyEncodedImageInspector.inspect(
|
|
162
|
+
ByteArrayInputStream("<svg xmlns=\"http://www.w3.org/2000/svg\"/>".toByteArray()),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
assertFalse(xml.animated)
|
|
166
|
+
assertFalse(svg.animated)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@Test
|
|
170
|
+
fun gifMetadataIsAnimatedAndUnsafeCanvasIsRejected() {
|
|
171
|
+
val safe = gifHeader(2048, 2048)
|
|
172
|
+
val metadata = OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(safe))
|
|
173
|
+
|
|
174
|
+
assertTrue(metadata.animated)
|
|
175
|
+
assertEquals(2048, metadata.width)
|
|
176
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
177
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(gifHeader(3000, 2000)))
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@Test
|
|
182
|
+
fun webpRequiresAnimationFlagAndChecksVp8xCanvas() {
|
|
183
|
+
val animated = OneKeyEncodedImageInspector.inspect(
|
|
184
|
+
ByteArrayInputStream(webpVp8x(2048, 2048, animated = true)),
|
|
185
|
+
)
|
|
186
|
+
val static = OneKeyEncodedImageInspector.inspect(
|
|
187
|
+
ByteArrayInputStream(webpVp8x(2048, 2048, animated = false)),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
assertTrue(animated.animated)
|
|
191
|
+
assertFalse(static.animated)
|
|
192
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
193
|
+
OneKeyEncodedImageInspector.inspect(
|
|
194
|
+
ByteArrayInputStream(webpVp8x(3000, 2000, animated = true)),
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
val ambiguous = webpVp8x(32, 32, animated = false).also {
|
|
198
|
+
"JUNK".toByteArray().copyInto(it, 12)
|
|
199
|
+
}
|
|
200
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
201
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(ambiguous))
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@Test
|
|
206
|
+
fun apngMetadataChecksCanvasAndFrameCountBeforeIdat() {
|
|
207
|
+
val metadata = OneKeyEncodedImageInspector.inspect(
|
|
208
|
+
ByteArrayInputStream(png(2048, 2048, frameCount = 12)),
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
assertTrue(metadata.animated)
|
|
212
|
+
assertEquals(12, metadata.frameCount)
|
|
213
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
214
|
+
OneKeyEncodedImageInspector.inspect(
|
|
215
|
+
ByteArrayInputStream(png(2048, 2048, frameCount = 1001)),
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
219
|
+
OneKeyEncodedImageInspector.inspect(
|
|
220
|
+
ByteArrayInputStream(png(3000, 2000, frameCount = 2)),
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@Test
|
|
226
|
+
fun pngWithOverlongMetadataFailsClosed() {
|
|
227
|
+
val image = ByteArrayOutputStream().apply {
|
|
228
|
+
write(png(32, 32, frameCount = null).copyOfRange(0, 33))
|
|
229
|
+
writeIntBe(this, 300_000)
|
|
230
|
+
write("tEXt".toByteArray())
|
|
231
|
+
}.toByteArray()
|
|
232
|
+
|
|
233
|
+
assertThrows(OneKeyImageSafetyException::class.java) {
|
|
234
|
+
OneKeyEncodedImageInspector.inspect(ByteArrayInputStream(image))
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@Test
|
|
239
|
+
fun safetyVersionParticipatesInMemoryAndDiskCacheIdentity() {
|
|
240
|
+
assertEquals("onekey-image-safety-v2", OneKeyImageSafetyVersionedKey.CACHE_VERSION)
|
|
241
|
+
val original = ObjectKey("custom-cache-key")
|
|
242
|
+
val first = OneKeyImageSafetyVersionedKey(original)
|
|
243
|
+
val same = OneKeyImageSafetyVersionedKey(ObjectKey("custom-cache-key"))
|
|
244
|
+
val originalDigest = MessageDigest.getInstance("SHA-256").apply {
|
|
245
|
+
original.updateDiskCacheKey(this)
|
|
246
|
+
}.digest()
|
|
247
|
+
val versionedDigest = MessageDigest.getInstance("SHA-256").apply {
|
|
248
|
+
first.updateDiskCacheKey(this)
|
|
249
|
+
}.digest()
|
|
250
|
+
|
|
251
|
+
assertEquals(first, same)
|
|
252
|
+
assertNotEquals(first, original)
|
|
253
|
+
assertFalse(originalDigest.contentEquals(versionedDigest))
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@Test
|
|
257
|
+
fun safetyFailureIsFoundInsideGlideRootsAndOrdinaryFailureIsNot() {
|
|
258
|
+
val safety = GlideException(
|
|
259
|
+
"request failed",
|
|
260
|
+
listOf(OneKeyImageSafetyException("too large")),
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
assertTrue(OneKeyImageSafety.isSafetyFailure(safety))
|
|
264
|
+
assertFalse(OneKeyImageSafety.isSafetyFailure(IOException("corrupt image")))
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private fun gifHeader(width: Int, height: Int): ByteArray = ByteArray(10).also { bytes ->
|
|
268
|
+
"GIF89a".toByteArray().copyInto(bytes)
|
|
269
|
+
bytes[6] = width.toByte()
|
|
270
|
+
bytes[7] = (width ushr 8).toByte()
|
|
271
|
+
bytes[8] = height.toByte()
|
|
272
|
+
bytes[9] = (height ushr 8).toByte()
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private fun webpVp8x(width: Int, height: Int, animated: Boolean): ByteArray =
|
|
276
|
+
ByteArray(30).also { bytes ->
|
|
277
|
+
"RIFF".toByteArray().copyInto(bytes, 0)
|
|
278
|
+
"WEBP".toByteArray().copyInto(bytes, 8)
|
|
279
|
+
"VP8X".toByteArray().copyInto(bytes, 12)
|
|
280
|
+
bytes[16] = 10
|
|
281
|
+
bytes[20] = if (animated) 0x02 else 0x00
|
|
282
|
+
write24Le(bytes, 24, width - 1)
|
|
283
|
+
write24Le(bytes, 27, height - 1)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private fun png(width: Int, height: Int, frameCount: Int?): ByteArray =
|
|
287
|
+
ByteArrayOutputStream().apply {
|
|
288
|
+
write(byteArrayOf(0x89.toByte(), 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a))
|
|
289
|
+
val ihdr = ByteArrayOutputStream().apply {
|
|
290
|
+
writeIntBe(this, width)
|
|
291
|
+
writeIntBe(this, height)
|
|
292
|
+
write(byteArrayOf(8, 6, 0, 0, 0))
|
|
293
|
+
}.toByteArray()
|
|
294
|
+
writeChunk(this, "IHDR", ihdr)
|
|
295
|
+
if (frameCount != null) {
|
|
296
|
+
val animation = ByteArrayOutputStream().apply {
|
|
297
|
+
writeIntBe(this, frameCount)
|
|
298
|
+
writeIntBe(this, 0)
|
|
299
|
+
}.toByteArray()
|
|
300
|
+
writeChunk(this, "acTL", animation)
|
|
301
|
+
} else {
|
|
302
|
+
writeChunk(this, "IDAT", byteArrayOf())
|
|
303
|
+
}
|
|
304
|
+
}.toByteArray()
|
|
305
|
+
|
|
306
|
+
private fun writeChunk(output: ByteArrayOutputStream, type: String, data: ByteArray) {
|
|
307
|
+
writeIntBe(output, data.size)
|
|
308
|
+
output.write(type.toByteArray())
|
|
309
|
+
output.write(data)
|
|
310
|
+
output.write(byteArrayOf(0, 0, 0, 0))
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private fun writeIntBe(output: ByteArrayOutputStream, value: Int) {
|
|
314
|
+
output.write((value ushr 24) and 0xff)
|
|
315
|
+
output.write((value ushr 16) and 0xff)
|
|
316
|
+
output.write((value ushr 8) and 0xff)
|
|
317
|
+
output.write(value and 0xff)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private fun write24Le(bytes: ByteArray, offset: Int, value: Int) {
|
|
321
|
+
bytes[offset] = value.toByte()
|
|
322
|
+
bytes[offset + 1] = (value ushr 8).toByte()
|
|
323
|
+
bytes[offset + 2] = (value ushr 16).toByte()
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private fun ftypPayload(majorBrand: String, vararg compatibleBrands: String): ByteArray =
|
|
327
|
+
ByteArrayOutputStream().apply {
|
|
328
|
+
write(majorBrand.toByteArray())
|
|
329
|
+
write(byteArrayOf(0, 0, 0, 0))
|
|
330
|
+
compatibleBrands.forEach { write(it.toByteArray()) }
|
|
331
|
+
}.toByteArray()
|
|
332
|
+
|
|
333
|
+
private fun bmffBox(type: String, payload: ByteArray, extended: Boolean = false): ByteArray =
|
|
334
|
+
ByteArrayOutputStream().apply {
|
|
335
|
+
if (extended) {
|
|
336
|
+
writeIntBe(this, 1)
|
|
337
|
+
write(type.toByteArray())
|
|
338
|
+
writeIntBe(this, 0)
|
|
339
|
+
writeIntBe(this, 16 + payload.size)
|
|
340
|
+
} else {
|
|
341
|
+
writeIntBe(this, 8 + payload.size)
|
|
342
|
+
write(type.toByteArray())
|
|
343
|
+
}
|
|
344
|
+
write(payload)
|
|
345
|
+
}.toByteArray()
|
|
346
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package com.margelo.nitro.onekeyimage
|
|
2
|
+
|
|
3
|
+
import org.junit.Assert.assertEquals
|
|
4
|
+
import org.junit.Assert.assertSame
|
|
5
|
+
import org.junit.Assert.assertThrows
|
|
6
|
+
import org.junit.Test
|
|
7
|
+
import java.io.IOException
|
|
8
|
+
|
|
9
|
+
class OneKeyResourceCleanupTest {
|
|
10
|
+
@Test
|
|
11
|
+
fun ordinaryDecoderExceptionsRecycleAndRethrowTheSameFailure() {
|
|
12
|
+
listOf<Exception>(IOException("corrupt"), IllegalStateException("invalid"))
|
|
13
|
+
.forEach { expected ->
|
|
14
|
+
var recycleCount = 0
|
|
15
|
+
|
|
16
|
+
val thrown = assertThrows(expected.javaClass) {
|
|
17
|
+
OneKeyResourceCleanup.recycleOnException(
|
|
18
|
+
recycle = { recycleCount += 1 },
|
|
19
|
+
block = { throw expected },
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
assertSame(expected, thrown)
|
|
24
|
+
assertEquals(1, recycleCount)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Test
|
|
29
|
+
fun errorsAreNotCaughtOrRecycled() {
|
|
30
|
+
val expected = AssertionError("fatal")
|
|
31
|
+
var recycleCount = 0
|
|
32
|
+
|
|
33
|
+
val thrown = assertThrows(AssertionError::class.java) {
|
|
34
|
+
OneKeyResourceCleanup.recycleOnException(
|
|
35
|
+
recycle = { recycleCount += 1 },
|
|
36
|
+
block = { throw expected },
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
assertSame(expected, thrown)
|
|
41
|
+
assertEquals(0, recycleCount)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package com.margelo.nitro.onekeyimage
|
|
2
|
+
|
|
3
|
+
import org.junit.Assert.assertEquals
|
|
4
|
+
import org.junit.Assert.assertThrows
|
|
5
|
+
import org.junit.Test
|
|
6
|
+
|
|
7
|
+
class OneKeyTerminalEventPairTest {
|
|
8
|
+
@Test
|
|
9
|
+
fun terminalPrimaryAndSnapshottedEndStayPairedDuringReentry() {
|
|
10
|
+
val events = mutableListOf<String>()
|
|
11
|
+
var currentEnd: () -> Unit = { events += "old-end" }
|
|
12
|
+
val snapshottedEnd = currentEnd
|
|
13
|
+
|
|
14
|
+
OneKeyTerminalEventPair.dispatch(
|
|
15
|
+
primary = {
|
|
16
|
+
events += "load"
|
|
17
|
+
currentEnd = { events += "new-end" }
|
|
18
|
+
},
|
|
19
|
+
onLoadEnd = snapshottedEnd,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
assertEquals(listOf("load", "old-end"), events)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Test
|
|
26
|
+
fun terminalEndStillRunsExactlyOnceWhenPrimaryThrows() {
|
|
27
|
+
var endCount = 0
|
|
28
|
+
|
|
29
|
+
assertThrows(IllegalStateException::class.java) {
|
|
30
|
+
OneKeyTerminalEventPair.dispatch(
|
|
31
|
+
primary = { throw IllegalStateException("callback failed") },
|
|
32
|
+
onLoadEnd = { endCount += 1 },
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
assertEquals(1, endCount)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package com.margelo.nitro.onekeyimage
|
|
2
|
+
|
|
3
|
+
import org.junit.Assert.assertEquals
|
|
4
|
+
import org.junit.Assert.assertTrue
|
|
5
|
+
import org.junit.Test
|
|
6
|
+
|
|
7
|
+
class OneKeyTosUrlTest {
|
|
8
|
+
@Test
|
|
9
|
+
fun selectsFirstBucketCoveringPhysicalOverscannedWidth() {
|
|
10
|
+
assertEquals(256, OneKeyTosUrl.selectWidthBucket(100, 2f, 1.1))
|
|
11
|
+
assertEquals(160, OneKeyTosUrl.selectWidthBucket(160, 1f, 1.0))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@Test
|
|
15
|
+
fun capsDprAndSelectionAtLargestBucket() {
|
|
16
|
+
assertEquals(480, OneKeyTosUrl.selectWidthBucket(100, 5f, 1.1))
|
|
17
|
+
assertEquals(1280, OneKeyTosUrl.selectWidthBucket(2000, 3f, 1.1))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Test
|
|
21
|
+
fun normalizesNonFiniteDensityAndOverscan() {
|
|
22
|
+
assertEquals(128, OneKeyTosUrl.selectWidthBucket(100, Float.NaN, 1.1))
|
|
23
|
+
assertEquals(128, OneKeyTosUrl.selectWidthBucket(100, Float.POSITIVE_INFINITY, 1.1))
|
|
24
|
+
assertEquals(200, OneKeyTosUrl.selectWidthBucket(100, 2f, Double.NaN))
|
|
25
|
+
assertEquals(200, OneKeyTosUrl.selectWidthBucket(100, 2f, Double.POSITIVE_INFINITY))
|
|
26
|
+
assertEquals(1280, OneKeyTosUrl.selectWidthBucket(100, 2f, Double.MAX_VALUE))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Test
|
|
30
|
+
fun optimizesOnlyApprovedOneKeyHosts() {
|
|
31
|
+
val allowedHosts = listOf(
|
|
32
|
+
"app-assets.onekey.so",
|
|
33
|
+
"uni.onekey-asset.com",
|
|
34
|
+
"uni-test.onekey-asset.com",
|
|
35
|
+
"common.onekey-asset.com",
|
|
36
|
+
"asset.onekey-asset.com",
|
|
37
|
+
)
|
|
38
|
+
allowedHosts.forEach { host ->
|
|
39
|
+
val result = OneKeyTosUrl.optimized(
|
|
40
|
+
"https://$host/token.png",
|
|
41
|
+
100,
|
|
42
|
+
2f,
|
|
43
|
+
1.1,
|
|
44
|
+
false,
|
|
45
|
+
)
|
|
46
|
+
assertTrue(result.contains("x-tos-process="))
|
|
47
|
+
assertTrue(result.contains("w_256"))
|
|
48
|
+
}
|
|
49
|
+
assertEquals(
|
|
50
|
+
"https://web.onekey-asset.com/token.png",
|
|
51
|
+
OneKeyTosUrl.optimized(
|
|
52
|
+
"https://web.onekey-asset.com/token.png",
|
|
53
|
+
100,
|
|
54
|
+
2f,
|
|
55
|
+
1.1,
|
|
56
|
+
false,
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Test
|
|
62
|
+
fun skipsProtectedQueriesAndUnsupportedMedia() {
|
|
63
|
+
val protectedKeys = listOf(
|
|
64
|
+
"expires", "policy", "signature", "token", "auth_key", "accesskeyid",
|
|
65
|
+
"ossaccesskeyid", "security-token", "x-amz-signature", "x-oss-signature",
|
|
66
|
+
"x-tos-process",
|
|
67
|
+
)
|
|
68
|
+
protectedKeys.forEach { key ->
|
|
69
|
+
val raw = "https://common.onekey-asset.com/token.png?$key=value"
|
|
70
|
+
assertEquals(raw, OneKeyTosUrl.optimized(raw, 100, 2f, 1.1, false))
|
|
71
|
+
}
|
|
72
|
+
listOf("svg", "mp4", "webm", "m4v", "mov", "avi").forEach { extension ->
|
|
73
|
+
val raw = "https://common.onekey-asset.com/media.$extension"
|
|
74
|
+
assertEquals(raw, OneKeyTosUrl.optimized(raw, 100, 2f, 1.1, false))
|
|
75
|
+
}
|
|
76
|
+
val customIdentity = "https://common.onekey-asset.com/token.png"
|
|
77
|
+
assertEquals(
|
|
78
|
+
customIdentity,
|
|
79
|
+
OneKeyTosUrl.optimized(customIdentity, 100, 2f, 1.1, true),
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
}
|