[go: nahoru, domu]

blob: 47bcddcd0921b2f183f3ca369fcc435273b8c6b0 [file] [log] [blame]
/*
* Copyright 2019 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 androidx.ui.core.gesture
import androidx.ui.core.IntPxSize
import androidx.ui.core.PxPosition
import androidx.ui.core.consumeDownChange
import androidx.ui.core.ipx
import androidx.ui.core.milliseconds
import androidx.ui.core.millisecondsToTimestamp
import androidx.ui.core.px
import androidx.ui.testutils.consume
import androidx.ui.testutils.down
import androidx.ui.testutils.invokeOverAllPasses
import androidx.ui.testutils.moveTo
import androidx.ui.testutils.up
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.verify
import kotlinx.coroutines.ObsoleteCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineContext
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import java.util.concurrent.TimeUnit
// TODO(shepshapard): Add more tests for:
// 1. More complex multi-pointer scenarios testing how consumption affects firing events
// 2. More complex multi-pointer scenarios testing how pointers effect consumption
@ObsoleteCoroutinesApi
@RunWith(JUnit4::class)
class DoubleTapGestureDetectorTest {
private val DoubleTapTimeoutMillis = 100.milliseconds
private val testContext = TestCoroutineContext()
private val onDoubleTap: (PxPosition) -> Unit = mock()
private lateinit var mRecognizer: DoubleTapGestureRecognizer
@Before
fun setup() {
mRecognizer = DoubleTapGestureRecognizer(testContext)
mRecognizer.onDoubleTap = onDoubleTap
mRecognizer.doubleTapTimeout = DoubleTapTimeoutMillis
}
// Tests that verify conditions under which onDoubleTap will not be called.
@Test
fun pointerInputHandler_down_onDoubleTapNotCalled() {
mRecognizer.pointerInputHandler.invokeOverAllPasses(listOf(down()))
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUp_onDoubleTapNotCalled() {
val down = down(timestamp = 0L.millisecondsToTimestamp())
val up = down.up(timestamp = 1L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownWithinTimeout_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 100L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownOutsideTimeout_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 101L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
testContext.advanceTimeBy(100, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownOutsideTimeoutUp_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 101L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(100, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downMoveConsumedUpDownInsideTimeoutUp_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val moveConsumed = down1.moveTo(1L.millisecondsToTimestamp(), x = 1f).consume(dx = 1f)
val up1 = moveConsumed.up(timestamp = 2L.millisecondsToTimestamp())
val down2 = down(timestamp = 101L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(moveConsumed)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownInsideTimeoutMoveConsumedUp_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 100L.millisecondsToTimestamp())
val moveConsumed = down2.moveTo(101L.millisecondsToTimestamp(), x = 1f).consume(dx = 1f)
val up2 = moveConsumed.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(moveConsumed)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_2Down1MoveConsumedUpDownInsideTimeoutUp_onDoubleTapNotCalled() {
val down1A = down(0, timestamp = 0L.millisecondsToTimestamp())
val down1B = down(1, timestamp = 0L.millisecondsToTimestamp())
val moveConsumed1A = down1A.moveTo(1L.millisecondsToTimestamp(), x = 1f).consume(dx = 1f)
val move1B = down1B.moveTo(1L.millisecondsToTimestamp())
val up1A = moveConsumed1A.up(timestamp = 2L.millisecondsToTimestamp())
val up1B = move1B.up(timestamp = 2L.millisecondsToTimestamp())
val down2 = down(timestamp = 101L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1A, down1B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(moveConsumed1A, move1B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1A, up1B)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUp2DownInsideTimeout1MoveConsumedUp_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up2 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2A = down(0, timestamp = 100L.millisecondsToTimestamp())
val down2B = down(1, timestamp = 100L.millisecondsToTimestamp())
val moveConsumed2A = down2A.moveTo(101L.millisecondsToTimestamp(), x = 1f).consume(dx = 1f)
val move2B = down2B.moveTo(101L.millisecondsToTimestamp())
val up2A = moveConsumed2A.up(timestamp = 102L.millisecondsToTimestamp())
val up2B = move2B.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2A, down2B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(moveConsumed2A, move2B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2A, up2B)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downConsumedUpDownWithinTimeoutUp_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp()).consumeDownChange()
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(0, timestamp = 100L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpConsumedDownWithinTimeoutUp_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp()).consumeDownChange()
val down2 = down(0, timestamp = 100L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownConsumedWithinTimeoutUp_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(0, timestamp = 100L.millisecondsToTimestamp()).consumeDownChange()
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownWithinTimeoutUpConsumed_onDoubleTapNotCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(0, timestamp = 100L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp()).consumeDownChange()
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_2down1Up1DownWithinTimeout1Up_onDoubleTapNotCalled() {
val down1A = down(0, timestamp = 0L.millisecondsToTimestamp())
val down1B = down(1, timestamp = 0L.millisecondsToTimestamp())
val move1A1 = down1A.moveTo(2L.millisecondsToTimestamp())
val up2B = down1B.up(timestamp = 2L.millisecondsToTimestamp())
val move1A2 = move1A1.moveTo(101L.millisecondsToTimestamp())
val down2 = down(id = 1, timestamp = 101L.millisecondsToTimestamp())
val move1A3 = move1A2.moveTo(102L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1A, down1B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move1A1, up2B)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move1A2, down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move1A3, up2)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_1down1Up2DownWithinTimeout1Up_onDoubleTapNotCalled() {
val down1 = down(id = 0, timestamp = 0L.millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2A = down(0, timestamp = 100L.millisecondsToTimestamp())
val down2B = down(1, timestamp = 100L.millisecondsToTimestamp())
val move2A = down2A.moveTo(timestamp = 101L.millisecondsToTimestamp())
val up2B = down2B.up(timestamp = 101L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2A, down2B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move2A, up2B)
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downMoveOutOfBoundsUpDownUp_onDoubleTapNotCalled() {
val down = down(0, 0L.millisecondsToTimestamp(), 0f, 0f)
val move = down.moveTo(1L.millisecondsToTimestamp(), 1f, 1f)
val up = move.up(timestamp = 12L.millisecondsToTimestamp())
val down2 = down(0, 13L.millisecondsToTimestamp(), 0f, 0f)
val up2 = down2.up(timestamp = 14L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(move, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2, IntPxSize(1.ipx, 1.ipx))
verify(onDoubleTap, never()).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownMoveOutOfBoundsUp_onDoubleTapNotCalled() {
val down = down(0, 0L.millisecondsToTimestamp(), 0f, 0f)
val up = down.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(0, 2L.millisecondsToTimestamp(), 0f, 0f)
val move2 = down2.moveTo(3L.millisecondsToTimestamp(), 1f, 1f)
val up2 = down2.up(timestamp = 4L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(move2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2, IntPxSize(1.ipx, 1.ipx))
verify(onDoubleTap, never()).invoke(any())
}
// Tests that verify conditions under which onDoubleTap will be called.
@Test
fun pointerInputHandler_downUpDownInsideTimeoutUp_onDoubleTapCalled() {
val down1 = down(timestamp = (0L).millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 100L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 101L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap).invoke(any())
}
@Test
fun pointerInputHandler_downMoveUpDownInsideTimeoutUp_onDoubleTapCalled() {
val down1 = down(timestamp = (0L).millisecondsToTimestamp())
val move = down1.moveTo(1L.millisecondsToTimestamp(), x = 1f)
val up1 = move.up(timestamp = 2L.millisecondsToTimestamp())
val down2 = down(timestamp = 101L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownInsideTimeoutMoveUp_onDoubleTapCalled() {
val down1 = down(timestamp = (0L).millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 10L.millisecondsToTimestamp())
val move = down2.moveTo(101L.millisecondsToTimestamp(), x = 1f)
val up2 = move.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap).invoke(any())
}
@Test
fun pointerInputHandler_2Down1MoveUpDownInsideTimeoutUp_onDoubleTapCalled() {
val down1A = down(0, timestamp = 0L.millisecondsToTimestamp())
val down1B = down(1, timestamp = 0L.millisecondsToTimestamp())
val move1A = down1A.moveTo(1L.millisecondsToTimestamp(), x = 1f)
val move1B = down1B.moveTo(1L.millisecondsToTimestamp())
val up1A = move1A.up(timestamp = 2L.millisecondsToTimestamp())
val up1B = move1B.up(timestamp = 2L.millisecondsToTimestamp())
val down2 = down(timestamp = 101L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1A, down1B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move1A, move1B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1A, up1B)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap).invoke(any())
}
@Test
fun pointerInputHandler_downUp2DownInsideTimeout1MoveUp_onDoubleTapCalled() {
val down1 = down(timestamp = 0L.millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2A = down(0, timestamp = 100L.millisecondsToTimestamp())
val down2B = down(1, timestamp = 100L.millisecondsToTimestamp())
val move2A = down2A.moveTo(101L.millisecondsToTimestamp(), x = 1f)
val move2B = down2B.moveTo(101L.millisecondsToTimestamp())
val up2A = move2A.up(timestamp = 102L.millisecondsToTimestamp())
val up2B = move2B.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2A, down2B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move2A, move2B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2A, up2B)
verify(onDoubleTap).invoke(any())
}
@Test
fun pointerInputHandler_downMoveOutOfBoundsUpDownUpDownUp_onDoubleTapCalledOnce() {
val down = down(0, 0L.millisecondsToTimestamp(), 0f, 0f)
val move = down.moveTo(1L.millisecondsToTimestamp(), 1f, 1f)
val up = move.up(timestamp = 2L.millisecondsToTimestamp())
val down2 = down(0, 3L.millisecondsToTimestamp(), 0f, 0f)
val up2 = down2.up(timestamp = 4L.millisecondsToTimestamp())
val down3 = down(0, 5L.millisecondsToTimestamp(), 0f, 0f)
val up3 = down3.up(6L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(move, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(down3, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up3, IntPxSize(1.ipx, 1.ipx))
verify(onDoubleTap).invoke(any())
}
@Test
fun pointerInputHandler_downUpDownMoveOutOfBoundsUpDownUpDownUp_onDoubleTapCalledOnce() {
val down = down(0, 0L.millisecondsToTimestamp(), 0f, 0f)
val up = down.up(timestamp = 2L.millisecondsToTimestamp())
val down2 = down(0, 3L.millisecondsToTimestamp(), 0f, 0f)
val move2 = down2.moveTo(1L.millisecondsToTimestamp(), 1f, 1f)
val up2 = move2.up(timestamp = 4L.millisecondsToTimestamp())
val down3 = down(0, 5L.millisecondsToTimestamp(), 0f, 0f)
val up3 = down3.up(6L.millisecondsToTimestamp())
val down4 = down(0, 7L.millisecondsToTimestamp(), 0f, 0f)
val up4 = down4.up(8L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(move2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(down3, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up3, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(down4, IntPxSize(1.ipx, 1.ipx))
mRecognizer.pointerInputHandler.invokeOverAllPasses(up4, IntPxSize(1.ipx, 1.ipx))
verify(onDoubleTap).invoke(any())
}
// Tests that verify correctness of PxPosition value passed to onDoubleTap
@Test
fun pointerInputHandler_downUpDownUpAllAtOrigin_onDoubleTapCalledWithOrigin() {
val down1 = down(timestamp = (0L).millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 100L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 101L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap).invoke(PxPosition.Origin)
}
@Test
fun pointerInputHandler_downUpDownMoveUp_onDoubleTapCalledWithFinalMovePosition() {
val down1 = down(timestamp = (0L).millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2 = down(timestamp = 100L.millisecondsToTimestamp())
val move2 = down2.moveTo(101L.millisecondsToTimestamp(), 3f, 5f)
val up2 = move2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
verify(onDoubleTap).invoke(PxPosition(3.px, 5.px))
}
@Test
fun pointerInputHandler_downUp2Down2Move1UpThen1Up_onDoubleTapCalledWithFinalFingerPosition() {
val down1 = down(timestamp = (0L).millisecondsToTimestamp())
val up1 = down1.up(timestamp = 1L.millisecondsToTimestamp())
val down2A = down(id = 0, timestamp = 100L.millisecondsToTimestamp())
val down2B = down(id = 1, timestamp = 100L.millisecondsToTimestamp())
val move2A = down2A.moveTo(101L.millisecondsToTimestamp(), 3f, 5f)
val move2B1 = down2B.moveTo(101L.millisecondsToTimestamp(), 7f, 11f)
val up2A = move2A.up(timestamp = 102L.millisecondsToTimestamp())
val move2B2 = move2B1.moveTo(timestamp = 102L.millisecondsToTimestamp(), x = 7f, y = 11f)
val up2B = move2B2.up(timestamp = 103L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up1)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2A, down2B)
mRecognizer.pointerInputHandler.invokeOverAllPasses(move2A, move2B1)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2A, move2B2)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up2B)
verify(onDoubleTap).invoke(PxPosition((7).px, (11).px))
}
// Tests that verify that consumption behavior
@Test
fun pointerInputHandler_down_downNotConsumed() {
val down = down()
val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
assertThat(result[0].consumed.downChange).isFalse()
}
@Test
fun pointerInputHandler_downUp_upNotConsumed() {
val down = down()
val up = down.up(1L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
assertThat(result[0].consumed.downChange).isFalse()
}
@Test
fun pointerInputHandler_downUpDownInsideTimeout_lastDownNotConsumed() {
val down = down()
val up = down.up(1L.millisecondsToTimestamp())
val down2 = down(timestamp = 100L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
assertThat(result[0].consumed.downChange).isFalse()
}
@Test
fun pointerInputHandler_downUpDownOutsideTimeoutUp_lastUpNotConsumed() {
val down = down()
val up = down.up(1L.millisecondsToTimestamp())
val down2 = down(timestamp = 101L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 102L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
testContext.advanceTimeBy(100, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
assertThat(result[0].consumed.downChange).isFalse()
}
@Test
fun pointerInputHandler_downUpDownInsideTimeoutUp_lastUpConsumed() {
val down = down()
val up = down.up(1L.millisecondsToTimestamp())
val down2 = down(timestamp = 100L.millisecondsToTimestamp())
val up2 = down2.up(timestamp = 101L.millisecondsToTimestamp())
mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
testContext.advanceTimeBy(99, TimeUnit.MILLISECONDS)
mRecognizer.pointerInputHandler.invokeOverAllPasses(down2)
val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(up2)
assertThat(result[0].consumed.downChange).isTrue()
}
}