• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download

<lambda>null1 package com.airbnb.lottie.snapshots.tests
2 
3 import android.util.Log
4 import com.airbnb.lottie.LottieCompositionFactory
5 import com.airbnb.lottie.snapshots.BuildConfig
6 import com.airbnb.lottie.snapshots.SnapshotTestCase
7 import com.airbnb.lottie.snapshots.SnapshotTestCaseContext
8 import com.airbnb.lottie.snapshots.snapshotComposition
9 import com.airbnb.lottie.snapshots.utils.await
10 import com.airbnb.lottie.snapshots.utils.retry
11 import com.amazonaws.auth.BasicAWSCredentials
12 import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility
13 import com.amazonaws.services.s3.AmazonS3Client
14 import com.amazonaws.services.s3.model.ListObjectsV2Request
15 import com.amazonaws.services.s3.model.S3ObjectSummary
16 import kotlinx.coroutines.CoroutineScope
17 import kotlinx.coroutines.Dispatchers
18 import kotlinx.coroutines.channels.Channel
19 import kotlinx.coroutines.channels.ReceiveChannel
20 import kotlinx.coroutines.channels.produce
21 import kotlinx.coroutines.coroutineScope
22 import kotlinx.coroutines.launch
23 import java.io.File
24 import java.io.FileInputStream
25 import java.util.concurrent.atomic.AtomicInteger
26 import java.util.zip.ZipInputStream
27 
28 /**
29  * TODO:
30  * prod-com.eharmony-lottie-loader-data
31  */
32 class ProdAnimationsTestCase : SnapshotTestCase {
33     private val filesChannel = Channel<File>(capacity = 2_048)
34 
35     override suspend fun SnapshotTestCaseContext.run() = coroutineScope {
36         val compositionsChannel = parseCompositions(filesChannel)
37         val num = AtomicInteger()
38         repeat(3) {
39             launch {
40                 for ((name, composition) in compositionsChannel) {
41                     Log.d(TAG, "Snapshot ${num.incrementAndGet()}")
42                     snapshotComposition(name, composition = composition)
43                 }
44             }
45         }
46     }
47 
48     @Suppress("BlockingMethodInNonBlockingContext")
49     fun CoroutineScope.parseCompositions(files: ReceiveChannel<File>) = produce(
50         context = Dispatchers.IO,
51         capacity = 50,
52     ) {
53         val num = AtomicInteger()
54         for (file in files) {
55             val result = if (file.name.endsWith("zip")) LottieCompositionFactory.fromZipStreamSync(ZipInputStream(FileInputStream(file)), null)
56             else LottieCompositionFactory.fromJsonInputStreamSync(FileInputStream(file), null)
57             val composition = result.value ?: throw IllegalStateException("Unable to parse ${file.nameWithoutExtension}", result.exception)
58             Log.d(TAG, "Parse ${num.incrementAndGet()}")
59             send("prod-${file.nameWithoutExtension}" to composition)
60         }
61     }
62 
63     suspend fun SnapshotTestCaseContext.downloadAnimations() = coroutineScope {
64         val transferUtility = TransferUtility.builder()
65             .context(context)
66             .s3Client(AmazonS3Client(BasicAWSCredentials(BuildConfig.S3AccessKey, BuildConfig.S3SecretKey)))
67             .defaultBucket("lottie-prod-animations")
68             .build()
69 
70         val num = AtomicInteger()
71         coroutineScope {
72             val animations = fetchAllObjects("lottie-prod-animations")
73             animations
74                 .chunked(animations.size / 4)
75                 .forEach { animationsChunk ->
76                     launch(Dispatchers.IO) {
77                         for (animation in animationsChunk) {
78                             val file = File(context.cacheDir, animation.key)
79                             file.deleteOnExit()
80                             retry { _, _ ->
81                                 transferUtility.download(animation.key, file).await()
82                             }
83                             Log.d(TAG, "Downloaded ${num.incrementAndGet()}")
84                             filesChannel.send(file)
85                         }
86                     }
87                 }
88         }
89         Log.d(TAG, "Finished downloading")
90         filesChannel.close()
91     }
92 
93     private fun fetchAllObjects(bucket: String): List<S3ObjectSummary> {
94         val allObjects = mutableListOf<S3ObjectSummary>()
95         val s3Client = AmazonS3Client(BasicAWSCredentials(BuildConfig.S3AccessKey, BuildConfig.S3SecretKey))
96         var request = ListObjectsV2Request().apply {
97             bucketName = bucket
98         }
99         var result = s3Client.listObjectsV2(request)
100         allObjects.addAll(result.objectSummaries)
101         var startAfter = result.objectSummaries.lastOrNull()?.key
102         while (startAfter != null) {
103             request = ListObjectsV2Request().apply {
104                 bucketName = bucket
105                 this.startAfter = startAfter
106             }
107             result = s3Client.listObjectsV2(request)
108             allObjects.addAll(result.objectSummaries)
109             startAfter = result.objectSummaries.lastOrNull()?.key
110         }
111         return allObjects
112     }
113 
114     companion object {
115         private const val TAG = "ProdAnimationsTest"
116     }
117 }