1 /*
<lambda>null2  * Copyright 2020 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 androidx.paging
18 
19 import androidx.paging.RemoteMediator.InitializeAction.SKIP_INITIAL_REFRESH
20 import kotlinx.coroutines.CancellationException
21 import kotlinx.coroutines.delay
22 
23 @OptIn(ExperimentalPagingApi::class)
24 typealias LoadCallback =
25     suspend (loadType: LoadType, state: PagingState<Int, Int>) -> RemoteMediator.MediatorResult?
26 
27 @OptIn(ExperimentalPagingApi::class)
28 open class RemoteMediatorMock(private val loadDelay: Long = 0) : RemoteMediator<Int, Int>() {
29     val loadEvents = mutableListOf<LoadEvent<Int, Int>>()
30     private val _newLoadEvents = mutableListOf<LoadEvent<Int, Int>>()
31     val newLoadEvents: List<LoadEvent<Int, Int>>
32         get() {
33             val result = _newLoadEvents.toList()
34             _newLoadEvents.clear()
35             return result
36         }
37 
38     val initializeEvents = mutableListOf<Unit>()
39 
40     val incompleteEvents = mutableListOf<LoadEvent<Int, Int>>()
41 
42     var initializeResult = SKIP_INITIAL_REFRESH
43 
44     var loadCallback: LoadCallback? = null
45 
46     private suspend fun defaultLoadCallback(
47         loadType: LoadType,
48         state: PagingState<Int, Int>
49     ): MediatorResult.Success {
50         try {
51             delay(loadDelay)
52         } catch (cancel: CancellationException) {
53             incompleteEvents.add(LoadEvent(loadType, state))
54             throw cancel
55         }
56         return MediatorResult.Success(false)
57     }
58 
59     override suspend fun load(loadType: LoadType, state: PagingState<Int, Int>): MediatorResult {
60         loadEvents.add(LoadEvent(loadType, state))
61         _newLoadEvents.add(LoadEvent(loadType, state))
62         return loadCallback?.invoke(loadType, state) ?: defaultLoadCallback(loadType, state)
63     }
64 
65     override suspend fun initialize(): InitializeAction {
66         initializeEvents.add(Unit)
67         return initializeResult
68     }
69 
70     fun loadEventCounts() =
71         LoadType.values().associateWith { loadType -> loadEvents.count { it.loadType == loadType } }
72 
73     data class LoadEvent<Key : Any, Value : Any>(
74         val loadType: LoadType,
75         val state: PagingState<Key, Value>?
76     )
77 }
78