1 /* 2 * Copyright (C) 2023 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.unfold.progress 18 19 import com.android.systemui.unfold.UnfoldTransitionProgressProvider 20 import com.android.systemui.util.leak.ReferenceTestUtils.waitForCondition 21 import com.google.common.truth.Truth.assertThat 22 import com.google.common.truth.Truth.assertWithMessage 23 24 /** Listener usable by tests with some handy assertions. */ 25 class TestUnfoldProgressListener : UnfoldTransitionProgressProvider.TransitionProgressListener { 26 27 private val recordings: MutableList<UnfoldTransitionRecording> = arrayListOf() 28 private var currentRecording: UnfoldTransitionRecording? = null 29 onTransitionStartednull30 override fun onTransitionStarted() { 31 assertWithMessage("Trying to start a transition when it is already in progress") 32 .that(currentRecording) 33 .isNull() 34 35 currentRecording = UnfoldTransitionRecording() 36 } 37 onTransitionProgressnull38 override fun onTransitionProgress(progress: Float) { 39 assertWithMessage("Received transition progress event when it's not started") 40 .that(currentRecording) 41 .isNotNull() 42 currentRecording!!.addProgress(progress) 43 } 44 onTransitionFinishingnull45 override fun onTransitionFinishing() { 46 assertWithMessage("Received transition finishing event when it's not started") 47 .that(currentRecording) 48 .isNotNull() 49 currentRecording!!.onFinishing() 50 } 51 onTransitionFinishednull52 override fun onTransitionFinished() { 53 assertWithMessage("Received transition finish event when it's not started") 54 .that(currentRecording) 55 .isNotNull() 56 recordings += currentRecording!! 57 currentRecording = null 58 } 59 ensureTransitionFinishednull60 fun ensureTransitionFinished(): UnfoldTransitionRecording { 61 waitForCondition { recordings.size == 1 } 62 return recordings.first() 63 } 64 assertStartednull65 fun assertStarted() { 66 assertWithMessage("Transition didn't start").that(currentRecording).isNotNull() 67 } 68 assertNotStartednull69 fun assertNotStarted() { 70 assertWithMessage("Transition started").that(currentRecording).isNull() 71 } 72 assertLastProgressnull73 fun assertLastProgress(progress: Float) { 74 currentRecording?.assertLastProgress(progress) ?: error("unfold not in progress.") 75 } 76 clearnull77 fun clear() { 78 currentRecording = null 79 recordings.clear() 80 } 81 82 class UnfoldTransitionRecording { 83 private val progressHistory: MutableList<Float> = arrayListOf() 84 private var finishingInvocations: Int = 0 85 addProgressnull86 fun addProgress(progress: Float) { 87 assertThat(progress).isAtMost(1.0f) 88 assertThat(progress).isAtLeast(0.0f) 89 90 progressHistory += progress 91 } 92 onFinishingnull93 fun onFinishing() { 94 finishingInvocations++ 95 } 96 assertIncreasingProgressnull97 fun assertIncreasingProgress() { 98 assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS) 99 assertThat(progressHistory).isInOrder() 100 } 101 assertDecreasingProgressnull102 fun assertDecreasingProgress() { 103 assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS) 104 assertThat(progressHistory).isInOrder(Comparator.reverseOrder<Float>()) 105 } 106 assertFinishedWithUnfoldnull107 fun assertFinishedWithUnfold() { 108 assertThat(progressHistory).isNotEmpty() 109 assertThat(progressHistory.last()).isEqualTo(1.0f) 110 } 111 assertFinishedWithFoldnull112 fun assertFinishedWithFold() { 113 assertThat(progressHistory).isNotEmpty() 114 assertThat(progressHistory.last()).isEqualTo(0.0f) 115 } 116 assertHasFoldAnimationAtTheEndnull117 fun assertHasFoldAnimationAtTheEnd() { 118 // Check that there are at least a few decreasing events at the end 119 assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS) 120 assertThat(progressHistory.takeLast(MIN_ANIMATION_EVENTS)) 121 .isInOrder(Comparator.reverseOrder<Float>()) 122 assertThat(progressHistory.last()).isEqualTo(0.0f) 123 } 124 assertHasSingleFinishingEventnull125 fun assertHasSingleFinishingEvent() { 126 assertWithMessage( 127 "onTransitionFinishing callback should be invoked exactly " + "one time" 128 ) 129 .that(finishingInvocations) 130 .isEqualTo(1) 131 } 132 assertLastProgressnull133 fun assertLastProgress(progress: Float) { 134 waitForCondition { progress == progressHistory.lastOrNull() } 135 } 136 } 137 138 private companion object { 139 private const val MIN_ANIMATION_EVENTS = 5 140 } 141 } 142