1 /* 2 * Copyright (C) 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.wm.shell.desktopmode.education 18 19 import android.content.Context 20 import android.testing.AndroidTestingRunner 21 import androidx.datastore.core.DataStore 22 import androidx.datastore.core.DataStoreFactory 23 import androidx.datastore.dataStoreFile 24 import androidx.test.core.app.ApplicationProvider 25 import androidx.test.filters.SmallTest 26 import androidx.test.platform.app.InstrumentationRegistry 27 import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository 28 import com.android.wm.shell.desktopmode.education.data.WindowingEducationProto 29 import com.android.wm.shell.util.GMAIL_PACKAGE_NAME 30 import com.android.wm.shell.util.createWindowingEducationProto 31 import com.google.common.truth.Truth.assertThat 32 import java.io.File 33 import java.time.Duration 34 import kotlinx.coroutines.CoroutineScope 35 import kotlinx.coroutines.Dispatchers 36 import kotlinx.coroutines.ExperimentalCoroutinesApi 37 import kotlinx.coroutines.SupervisorJob 38 import kotlinx.coroutines.cancel 39 import kotlinx.coroutines.flow.first 40 import kotlinx.coroutines.test.StandardTestDispatcher 41 import kotlinx.coroutines.test.runTest 42 import kotlinx.coroutines.test.setMain 43 import org.junit.After 44 import org.junit.Before 45 import org.junit.Test 46 import org.junit.runner.RunWith 47 48 @SmallTest 49 @RunWith(AndroidTestingRunner::class) 50 @ExperimentalCoroutinesApi 51 class AppHandleEducationDatastoreRepositoryTest { 52 private val testContext: Context = InstrumentationRegistry.getInstrumentation().targetContext 53 private lateinit var testDatastore: DataStore<WindowingEducationProto> 54 private lateinit var datastoreRepository: AppHandleEducationDatastoreRepository 55 private lateinit var datastoreScope: CoroutineScope 56 57 @Before setUpnull58 fun setUp() { 59 Dispatchers.setMain(StandardTestDispatcher()) 60 datastoreScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) 61 testDatastore = 62 DataStoreFactory.create( 63 serializer = 64 AppHandleEducationDatastoreRepository.Companion 65 .WindowingEducationProtoSerializer, 66 scope = datastoreScope, 67 ) { 68 testContext.dataStoreFile(APP_HANDLE_EDUCATION_DATASTORE_TEST_FILE) 69 } 70 datastoreRepository = AppHandleEducationDatastoreRepository(testDatastore) 71 } 72 73 @After tearDownnull74 fun tearDown() { 75 File(ApplicationProvider.getApplicationContext<Context>().filesDir, "datastore") 76 .deleteRecursively() 77 78 datastoreScope.cancel() 79 } 80 81 @Test getWindowingEducationProto_returnsCorrectProtonull82 fun getWindowingEducationProto_returnsCorrectProto() = 83 runTest(StandardTestDispatcher()) { 84 val windowingEducationProto = 85 createWindowingEducationProto( 86 appHandleHintViewedTimestampMillis = 123L, 87 appHandleHintUsedTimestampMillis = 124L, 88 appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 2), 89 appUsageStatsLastUpdateTimestampMillis = 125L, 90 ) 91 testDatastore.updateData { windowingEducationProto } 92 93 val resultProto = datastoreRepository.windowingEducationProto() 94 95 assertThat(resultProto).isEqualTo(windowingEducationProto) 96 } 97 98 @Test updateAppUsageStats_updatesDatastoreProtonull99 fun updateAppUsageStats_updatesDatastoreProto() = 100 runTest(StandardTestDispatcher()) { 101 val appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 3) 102 val appUsageStatsLastUpdateTimestamp = Duration.ofMillis(123L) 103 val windowingEducationProto = 104 createWindowingEducationProto( 105 appUsageStats = appUsageStats, 106 appUsageStatsLastUpdateTimestampMillis = 107 appUsageStatsLastUpdateTimestamp.toMillis(), 108 ) 109 110 datastoreRepository.updateAppUsageStats(appUsageStats, appUsageStatsLastUpdateTimestamp) 111 112 val result = testDatastore.data.first() 113 assertThat(result).isEqualTo(windowingEducationProto) 114 } 115 116 @Test updateAppHandleHintViewedTimestampMillis_updatesDatastoreProtonull117 fun updateAppHandleHintViewedTimestampMillis_updatesDatastoreProto() = 118 runTest(StandardTestDispatcher()) { 119 datastoreRepository.updateAppHandleHintViewedTimestampMillis(true) 120 121 val result = testDatastore.data.first().hasAppHandleHintViewedTimestampMillis() 122 assertThat(result).isEqualTo(true) 123 } 124 125 @Test updateEnterDesktopModeHintViewedTimestampMillis_updatesDatastoreProtonull126 fun updateEnterDesktopModeHintViewedTimestampMillis_updatesDatastoreProto() = 127 runTest(StandardTestDispatcher()) { 128 datastoreRepository.updateEnterDesktopModeHintViewedTimestampMillis(true) 129 130 val result = testDatastore.data.first().hasEnterDesktopModeHintViewedTimestampMillis() 131 assertThat(result).isEqualTo(true) 132 } 133 134 @Test updateExitDesktopModeHintViewedTimestampMillis_updatesDatastoreProtonull135 fun updateExitDesktopModeHintViewedTimestampMillis_updatesDatastoreProto() = 136 runTest(StandardTestDispatcher()) { 137 datastoreRepository.updateExitDesktopModeHintViewedTimestampMillis(true) 138 139 val result = testDatastore.data.first().hasExitDesktopModeHintViewedTimestampMillis() 140 assertThat(result).isEqualTo(true) 141 } 142 143 @Test updateAppHandleHintUsedTimestampMillis_updatesDatastoreProtonull144 fun updateAppHandleHintUsedTimestampMillis_updatesDatastoreProto() = 145 runTest(StandardTestDispatcher()) { 146 datastoreRepository.updateAppHandleHintUsedTimestampMillis(true) 147 148 val result = testDatastore.data.first().hasAppHandleHintUsedTimestampMillis() 149 assertThat(result).isEqualTo(true) 150 } 151 152 companion object { 153 private const val APP_HANDLE_EDUCATION_DATASTORE_TEST_FILE = "app_handle_education_test.pb" 154 } 155 } 156