| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.systemui.statusbar.notification.collection.notifcollection |
| |
| import android.os.Handler |
| import android.testing.AndroidTestingRunner |
| import android.testing.TestableLooper.RunWithLooper |
| import androidx.test.filters.SmallTest |
| import com.android.systemui.SysuiTestCase |
| import com.android.systemui.statusbar.notification.collection.NotificationEntry |
| import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder |
| import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback |
| import com.android.systemui.util.mockito.withArgCaptor |
| import com.google.common.truth.Truth.assertThat |
| import org.junit.Before |
| import org.junit.Test |
| import org.junit.runner.RunWith |
| import org.mockito.Mock |
| import org.mockito.Mockito.`when` |
| import org.mockito.Mockito.any |
| import org.mockito.Mockito.anyLong |
| import org.mockito.Mockito.eq |
| import org.mockito.Mockito.never |
| import org.mockito.Mockito.times |
| import org.mockito.Mockito.verify |
| import org.mockito.MockitoAnnotations.initMocks |
| import java.util.function.Consumer |
| import java.util.function.Predicate |
| |
| @SmallTest |
| @RunWith(AndroidTestingRunner::class) |
| @RunWithLooper |
| class SelfTrackingLifetimeExtenderTest : SysuiTestCase() { |
| private lateinit var extender: TestableSelfTrackingLifetimeExtender |
| |
| private lateinit var entry1: NotificationEntry |
| private lateinit var entry2: NotificationEntry |
| |
| @Mock |
| private lateinit var callback: OnEndLifetimeExtensionCallback |
| @Mock |
| private lateinit var mainHandler: Handler |
| @Mock |
| private lateinit var shouldExtend: Predicate<NotificationEntry> |
| @Mock |
| private lateinit var onStarted: Consumer<NotificationEntry> |
| @Mock |
| private lateinit var onCanceled: Consumer<NotificationEntry> |
| |
| @Before |
| fun setUp() { |
| initMocks(this) |
| extender = TestableSelfTrackingLifetimeExtender() |
| extender.setCallback(callback) |
| entry1 = NotificationEntryBuilder().setId(1).build() |
| entry2 = NotificationEntryBuilder().setId(2).build() |
| } |
| |
| @Test |
| fun testName() { |
| assertThat(extender.name).isEqualTo("Testable") |
| } |
| |
| @Test |
| fun testNoExtend() { |
| `when`(shouldExtend.test(entry1)).thenReturn(false) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isFalse() |
| assertThat(extender.isExtending(entry1.key)).isFalse() |
| verify(onStarted, never()).accept(entry1) |
| verify(onCanceled, never()).accept(entry1) |
| } |
| |
| @Test |
| fun testExtendThenCancelForRepost() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted).accept(entry1) |
| verify(onCanceled, never()).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| extender.cancelLifetimeExtension(entry1) |
| verify(onCanceled).accept(entry1) |
| } |
| |
| @Test |
| fun testExtendThenCancel_thenEndDoesNothing() { |
| testExtendThenCancelForRepost() |
| assertThat(extender.isExtending(entry1.key)).isFalse() |
| |
| extender.endLifetimeExtension(entry1.key) |
| extender.endLifetimeExtensionAfterDelay(entry1.key, 1000) |
| verify(callback, never()).onEndLifetimeExtension(any(), any()) |
| verify(mainHandler, never()).postDelayed(any(), anyLong()) |
| } |
| |
| @Test |
| fun testExtendThenEnd() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| extender.endLifetimeExtension(entry1.key) |
| verify(callback).onEndLifetimeExtension(extender, entry1) |
| verify(onCanceled, never()).accept(entry1) |
| } |
| |
| @Test |
| fun testExtendThenEndAfterDelay() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| |
| // Call the method and capture the posted runnable |
| extender.endLifetimeExtensionAfterDelay(entry1.key, 1234) |
| val runnable = withArgCaptor<Runnable> { |
| verify(mainHandler).postDelayed(capture(), eq(1234.toLong())) |
| } |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| verify(callback, never()).onEndLifetimeExtension(any(), any()) |
| |
| // now run the posted runnable and ensure it works as expected |
| runnable.run() |
| verify(callback).onEndLifetimeExtension(extender, entry1) |
| assertThat(extender.isExtending(entry1.key)).isFalse() |
| verify(onCanceled, never()).accept(entry1) |
| } |
| |
| @Test |
| fun testExtendThenEndAll() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true) |
| `when`(shouldExtend.test(entry2)).thenReturn(true) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| assertThat(extender.isExtending(entry2.key)).isFalse() |
| assertThat(extender.shouldExtendLifetime(entry2, 0)).isTrue() |
| verify(onStarted).accept(entry2) |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| assertThat(extender.isExtending(entry2.key)).isTrue() |
| extender.endAllLifetimeExtensions() |
| verify(callback).onEndLifetimeExtension(extender, entry1) |
| verify(callback).onEndLifetimeExtension(extender, entry2) |
| verify(onCanceled, never()).accept(entry1) |
| verify(onCanceled, never()).accept(entry2) |
| } |
| |
| @Test |
| fun testExtendWithinEndCanReExtend() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted, times(1)).accept(entry1) |
| |
| `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer { |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| } |
| extender.endLifetimeExtension(entry1.key) |
| verify(onStarted, times(2)).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| } |
| |
| @Test |
| fun testExtendWithinEndCanNotReExtend() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true, false) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted, times(1)).accept(entry1) |
| |
| `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer { |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isFalse() |
| } |
| extender.endLifetimeExtension(entry1.key) |
| verify(onStarted, times(1)).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isFalse() |
| } |
| |
| @Test |
| fun testExtendWithinEndAllCanReExtend() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted, times(1)).accept(entry1) |
| |
| `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer { |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| } |
| extender.endAllLifetimeExtensions() |
| verify(onStarted, times(2)).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isTrue() |
| } |
| |
| @Test |
| fun testExtendWithinEndAllCanNotReExtend() { |
| `when`(shouldExtend.test(entry1)).thenReturn(true, false) |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isTrue() |
| verify(onStarted, times(1)).accept(entry1) |
| |
| `when`(callback.onEndLifetimeExtension(extender, entry1)).thenAnswer { |
| assertThat(extender.shouldExtendLifetime(entry1, 0)).isFalse() |
| } |
| extender.endAllLifetimeExtensions() |
| verify(onStarted, times(1)).accept(entry1) |
| assertThat(extender.isExtending(entry1.key)).isFalse() |
| } |
| |
| inner class TestableSelfTrackingLifetimeExtender(debug: Boolean = false) : |
| SelfTrackingLifetimeExtender("Test", "Testable", debug, mainHandler) { |
| |
| override fun queryShouldExtendLifetime(entry: NotificationEntry) = |
| shouldExtend.test(entry) |
| |
| override fun onStartedLifetimeExtension(entry: NotificationEntry) { |
| onStarted.accept(entry) |
| } |
| |
| override fun onCanceledLifetimeExtension(entry: NotificationEntry) { |
| onCanceled.accept(entry) |
| } |
| } |
| } |