Jelle Fresen | ae8fbfc | 2020-06-02 17:54:26 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2020 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 androidx.ui.test.inputdispatcher |
| 18 | |
| 19 | import android.view.MotionEvent.ACTION_DOWN |
| 20 | import android.view.MotionEvent.ACTION_MOVE |
| 21 | import android.view.MotionEvent.ACTION_UP |
| 22 | import androidx.test.filters.SmallTest |
Jelle Fresen | 4c25bda | 2020-06-15 19:29:59 +0100 | [diff] [blame] | 23 | import androidx.ui.test.InputDispatcher.InputDispatcherTestRule |
Jelle Fresen | ae8fbfc | 2020-06-02 17:54:26 +0100 | [diff] [blame] | 24 | import androidx.ui.test.android.AndroidInputDispatcher |
| 25 | import androidx.ui.test.util.MotionEventRecorder |
| 26 | import androidx.ui.test.util.assertHasValidEventTimes |
| 27 | import androidx.ui.test.util.verify |
| 28 | import androidx.ui.unit.Duration |
Jelle Fresen | ae8fbfc | 2020-06-02 17:54:26 +0100 | [diff] [blame] | 29 | import androidx.ui.unit.inMilliseconds |
| 30 | import androidx.ui.unit.milliseconds |
| 31 | import com.google.common.truth.Truth.assertThat |
| 32 | import org.junit.After |
| 33 | import org.junit.Before |
| 34 | import org.junit.Rule |
| 35 | import org.junit.Test |
| 36 | import org.junit.rules.TestRule |
| 37 | import org.junit.runner.RunWith |
| 38 | import org.junit.runners.Parameterized |
| 39 | |
| 40 | /** |
| 41 | * Tests if the [AndroidInputDispatcher.sendSwipe] gesture works when specifying the gesture as a |
| 42 | * function between two positions. Verifies if the generated MotionEvents for a gesture with a |
| 43 | * given duration and a set of keyTimes have the expected timestamps. The timestamps should |
| 44 | * include all keyTimes, and divide the duration between those keyTimes as equally as possible |
| 45 | * with as close to [AndroidInputDispatcher.eventPeriod] between each successive event as possible. |
| 46 | */ |
| 47 | @SmallTest |
| 48 | @RunWith(Parameterized::class) |
| 49 | class SendSwipeWithKeyTimesTest(private val config: TestConfig) { |
| 50 | data class TestConfig( |
| 51 | val duration: Duration, |
| 52 | val keyTimes: List<Long>, |
| 53 | val expectedTimestamps: List<Long> |
| 54 | ) |
| 55 | |
| 56 | companion object { |
| 57 | private val curve = { t: Long -> |
Nader Jawad | 6df0612 | 2020-06-03 15:27:08 -0700 | [diff] [blame] | 58 | androidx.ui.geometry.Offset(t.toFloat(), (-t).toFloat()) |
Jelle Fresen | ae8fbfc | 2020-06-02 17:54:26 +0100 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | @JvmStatic |
| 62 | @Parameterized.Parameters(name = "{0}") |
| 63 | fun createTestSet(): List<TestConfig> { |
| 64 | return listOf( |
| 65 | // 10.ms normally splits into 1 event, but here we add a keyTime that must yield |
| 66 | // an event at that time |
| 67 | TestConfig(10.milliseconds, listOf(1), listOf(1, 10)), |
| 68 | TestConfig(10.milliseconds, listOf(2), listOf(2, 10)), |
| 69 | TestConfig(10.milliseconds, listOf(3), listOf(3, 10)), |
| 70 | TestConfig(10.milliseconds, listOf(4), listOf(4, 10)), |
| 71 | TestConfig(10.milliseconds, listOf(5), listOf(5, 10)), |
| 72 | TestConfig(10.milliseconds, listOf(6), listOf(6, 10)), |
| 73 | TestConfig(10.milliseconds, listOf(7), listOf(7, 10)), |
| 74 | TestConfig(10.milliseconds, listOf(8), listOf(8, 10)), |
| 75 | TestConfig(10.milliseconds, listOf(9), listOf(9, 10)), |
| 76 | // With 2 keyTimes we expect to see both those keyTimes in the generated events |
| 77 | TestConfig(10.milliseconds, listOf(1, 9), listOf(1, 9, 10)), |
| 78 | // Same for 3 keyTimes |
| 79 | TestConfig(10.milliseconds, listOf(1, 5, 9), listOf(1, 5, 9, 10)), |
| 80 | // If two keyTimes are longer than eventPeriod apart from each other, that period |
| 81 | // must be split as usual (here: between 10 and 28) |
| 82 | TestConfig(30.milliseconds, listOf(5, 10, 28), listOf(5, 10, 19, 28, 30)) |
| 83 | ) |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | @get:Rule |
Jelle Fresen | 4c25bda | 2020-06-15 19:29:59 +0100 | [diff] [blame] | 88 | val inputDispatcherRule: TestRule = InputDispatcherTestRule(disableDispatchInRealTime = true) |
Jelle Fresen | ae8fbfc | 2020-06-02 17:54:26 +0100 | [diff] [blame] | 89 | |
| 90 | private val recorder = MotionEventRecorder() |
| 91 | private val subject = AndroidInputDispatcher(recorder::recordEvent) |
| 92 | |
| 93 | @Before |
| 94 | fun setUp() { |
| 95 | require(config.keyTimes.distinct() == config.keyTimes.distinct().sorted()) { |
| 96 | "keyTimes needs to be sorted, not ${config.keyTimes}" |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | @After |
| 101 | fun tearDown() { |
| 102 | recorder.disposeEvents() |
| 103 | } |
| 104 | |
| 105 | @Test |
| 106 | fun swipeWithKeyTimes() { |
| 107 | // Given a swipe with a given duration and set of keyTimes |
| 108 | subject.sendSwipe(curve = curve, duration = config.duration, keyTimes = config.keyTimes) |
| 109 | |
| 110 | // then |
| 111 | val expectedNumberOfMoveEvents = config.expectedTimestamps.size |
| 112 | recorder.assertHasValidEventTimes() |
| 113 | recorder.events.apply { |
| 114 | // down + up + #move |
| 115 | assertThat(size).isEqualTo(2 + expectedNumberOfMoveEvents) |
| 116 | |
| 117 | val durationMs = config.duration.inMilliseconds() |
| 118 | // First is down, last is up |
| 119 | first().verify(curve, ACTION_DOWN, expectedRelativeTime = 0) |
| 120 | last().verify(curve, ACTION_UP, expectedRelativeTime = durationMs) |
| 121 | // In between are all move events with the expected timestamps |
| 122 | drop(1).zip(config.expectedTimestamps).forEach { (event, expectedTimestamp) -> |
| 123 | event.verify(curve, ACTION_MOVE, expectedRelativeTime = expectedTimestamp) |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | } |