1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.photopicker.test.utils
18 
19 import androidx.compose.ui.test.IdlingResource
20 import java.util.concurrent.atomic.AtomicInteger
21 
22 /**
23  * A test helper that ensures that the ComposeTestRule can be made aware of Glide's asynchronous
24  * operations.
25  *
26  * This is a very simple implementation of a Counting based IdlingResource. Each new Glide load that
27  * is started should call [loadStarted], and then call [loadFinished] when it either fails, or
28  * completes.
29  *
30  * Any time that the number of pending loads is equal to Zero, this IdlingResource will represent
31  * itself as idle.
32  */
33 class GlideLoadableIdlingResource : IdlingResource {
34 
35     // Are there any currently pending loads?
36     override val isIdleNow: Boolean
37         get() = _isIdleNow()
38 
getDiagnosticMessageIfBusynull39     override fun getDiagnosticMessageIfBusy(): String? {
40         return when (_isIdleNow()) {
41             true -> "Glide has $pending loads that are still pending."
42             false -> null
43         }
44     }
45 
46     // The number of pending loads
47     private var pending = AtomicInteger(0)
48 
49     /** Considered to be idle when there are no pending loads going on. */
_isIdleNownull50     private fun _isIdleNow(): Boolean {
51         return pending.get() == 0
52     }
53 
54     /**
55      * Increases the number of pending loads. Be sure that
56      * [GlideLoadableIdlingResource#loadFinished] is eventually called, or this IdlingResource will
57      * never register as idle.
58      */
loadStartednull59     fun loadStarted() {
60         pending.incrementAndGet()
61     }
62 
63     /**
64      * Decrease the number of pending loads.
65      *
66      * This is the equivalent of marking one pending load as completed.
67      */
loadFinishednull68     fun loadFinished() {
69         pending.decrementAndGet()
70     }
71 
72     /** Ignore all pending loads, and reset state to initialization. */
resetnull73     fun reset() {
74         pending.set(0)
75     }
76 }
77