1 /* 2 * Copyright (C) 2021 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.systemui.statusbar.policy 18 19 import android.os.Handler 20 import android.testing.AndroidTestingRunner 21 import android.testing.TestableLooper 22 import androidx.test.filters.SmallTest 23 import com.android.systemui.SysuiTestCase 24 import com.android.systemui.broadcast.BroadcastDispatcher 25 import com.android.systemui.util.mockito.any 26 import com.android.systemui.util.mockito.capture 27 import com.android.systemui.util.mockito.mock 28 import com.android.systemui.util.time.FakeSystemClock 29 import com.google.common.truth.Truth.assertThat 30 import org.junit.Before 31 import org.junit.Test 32 import org.junit.runner.RunWith 33 import org.mockito.ArgumentCaptor 34 import org.mockito.Captor 35 import org.mockito.Mock 36 import org.mockito.Mockito.`when` 37 import org.mockito.Mockito.anyString 38 import org.mockito.Mockito.verify 39 import org.mockito.MockitoAnnotations 40 import java.util.Date 41 42 @RunWith(AndroidTestingRunner::class) 43 @TestableLooper.RunWithLooper 44 @SmallTest 45 class VariableDateViewControllerTest : SysuiTestCase() { 46 47 companion object { 48 private const val TIME_STAMP = 1_500_000_000_000 49 private const val LONG_PATTERN = "EEEMMMd" 50 private const val SHORT_PATTERN = "MMMd" 51 private const val CHAR_WIDTH = 10f 52 } 53 54 @Mock 55 private lateinit var broadcastDispatcher: BroadcastDispatcher 56 @Mock 57 private lateinit var view: VariableDateView 58 @Captor 59 private lateinit var onMeasureListenerCaptor: ArgumentCaptor<VariableDateView.OnMeasureListener> 60 61 private var lastText: String? = null 62 63 private lateinit var systemClock: FakeSystemClock 64 private lateinit var testableLooper: TestableLooper 65 private lateinit var testableHandler: Handler 66 private lateinit var controller: VariableDateViewController 67 68 private lateinit var longText: String 69 private lateinit var shortText: String 70 71 @Before 72 fun setUp() { 73 MockitoAnnotations.initMocks(this) 74 testableLooper = TestableLooper.get(this) 75 testableHandler = Handler(testableLooper.looper) 76 77 systemClock = FakeSystemClock() 78 systemClock.setCurrentTimeMillis(TIME_STAMP) 79 80 `when`(view.longerPattern).thenReturn(LONG_PATTERN) 81 `when`(view.shorterPattern).thenReturn(SHORT_PATTERN) 82 `when`(view.handler).thenReturn(testableHandler) 83 84 `when`(view.setText(anyString())).thenAnswer { 85 lastText = it.arguments[0] as? String 86 Unit 87 } 88 `when`(view.isAttachedToWindow).thenReturn(true) 89 90 val date = Date(TIME_STAMP) 91 longText = getTextForFormat(date, getFormatFromPattern(LONG_PATTERN)) 92 shortText = getTextForFormat(date, getFormatFromPattern(SHORT_PATTERN)) 93 94 // Assume some sizes for the text, the controller doesn't need to know if these sizes are 95 // the true ones 96 `when`(view.getDesiredWidthForText(any())).thenAnswer { 97 getTextLength(it.arguments[0] as CharSequence) 98 } 99 100 controller = VariableDateViewController( 101 systemClock, 102 broadcastDispatcher, 103 mock(), 104 testableHandler, 105 view 106 ) 107 108 controller.init() 109 testableLooper.processAllMessages() 110 111 verify(view).onAttach(capture(onMeasureListenerCaptor)) 112 } 113 114 @Test 115 fun testViewStartsWithLongText() { 116 assertThat(lastText).isEqualTo(longText) 117 } 118 119 @Test 120 fun testListenerNotNull() { 121 assertThat(onMeasureListenerCaptor.value).isNotNull() 122 } 123 124 @Test 125 fun testLotsOfSpaceUseLongText() { 126 onMeasureListenerCaptor.value.onMeasureAction(10000) 127 128 testableLooper.processAllMessages() 129 assertThat(lastText).isEqualTo(longText) 130 } 131 132 @Test 133 fun testSmallSpaceUseEmpty() { 134 onMeasureListenerCaptor.value.onMeasureAction(1) 135 testableLooper.processAllMessages() 136 137 assertThat(lastText).isEmpty() 138 } 139 140 @Test 141 fun testSpaceInBetweenUseShortText() { 142 val average = ((getTextLength(longText) + getTextLength(shortText)) / 2).toInt() 143 144 onMeasureListenerCaptor.value.onMeasureAction(average) 145 testableLooper.processAllMessages() 146 147 assertThat(lastText).isEqualTo(shortText) 148 } 149 150 @Test 151 fun testSwitchBackToLonger() { 152 onMeasureListenerCaptor.value.onMeasureAction(1) 153 testableLooper.processAllMessages() 154 155 onMeasureListenerCaptor.value.onMeasureAction(10000) 156 testableLooper.processAllMessages() 157 158 assertThat(lastText).isEqualTo(longText) 159 } 160 161 @Test 162 fun testNoSwitchingWhenFrozen() { 163 `when`(view.freezeSwitching).thenReturn(true) 164 165 val average = ((getTextLength(longText) + getTextLength(shortText)) / 2).toInt() 166 onMeasureListenerCaptor.value.onMeasureAction(average) 167 testableLooper.processAllMessages() 168 assertThat(lastText).isEqualTo(longText) 169 170 onMeasureListenerCaptor.value.onMeasureAction(1) 171 testableLooper.processAllMessages() 172 assertThat(lastText).isEqualTo(longText) 173 } 174 175 private fun getTextLength(text: CharSequence): Float { 176 return text.length * CHAR_WIDTH 177 } 178 }