blob: 4219df6bb8da9d777b6fb089e08903fd79b822bf [file]
/*
* Copyright (C) 2024 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.mechanics.spec
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.mechanics.spring.SpringParameters
import com.google.common.truth.Truth.assertThat
import kotlin.math.nextDown
import kotlin.math.nextUp
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class DirectionalMotionSpecTest {
@Test
fun noBreakpoints_throws() {
assertFailsWith<IllegalArgumentException> {
DirectionalMotionSpec(emptyList(), emptyList())
}
}
@Test
fun wrongSentinelBreakpoints_throws() {
val breakpoint1 = Breakpoint(b1, position = 10f, spring, Guarantee.None)
val breakpoint2 = Breakpoint(b2, position = 20f, spring, Guarantee.None)
assertFailsWith<IllegalArgumentException> {
DirectionalMotionSpec(listOf(breakpoint1, breakpoint2), listOf(Mapping.Identity))
}
}
@Test
fun tooFewMappings_throws() {
assertFailsWith<IllegalArgumentException> {
DirectionalMotionSpec(listOf(Breakpoint.minLimit, Breakpoint.maxLimit), emptyList())
}
}
@Test
fun tooManyMappings_throws() {
assertFailsWith<IllegalArgumentException> {
DirectionalMotionSpec(
listOf(Breakpoint.minLimit, Breakpoint.maxLimit),
listOf(Mapping.One, Mapping.Two),
)
}
}
@Test
fun breakpointsOutOfOrder_throws() {
val breakpoint1 = Breakpoint(b1, position = 10f, spring, Guarantee.None)
val breakpoint2 = Breakpoint(b2, position = 20f, spring, Guarantee.None)
assertFailsWith<IllegalArgumentException> {
DirectionalMotionSpec(
listOf(Breakpoint.minLimit, breakpoint2, breakpoint1, Breakpoint.maxLimit),
listOf(Mapping.Zero, Mapping.One, Mapping.Two),
)
}
}
@Test
fun findBreakpointIndex_returnsMinForEmptySpec() {
val underTest = DirectionalMotionSpec.builder(spring).complete()
assertThat(underTest.findBreakpointIndex(0f)).isEqualTo(0)
assertThat(underTest.findBreakpointIndex(Float.MAX_VALUE)).isEqualTo(0)
assertThat(underTest.findBreakpointIndex(-Float.MAX_VALUE)).isEqualTo(0)
}
@Test
fun findBreakpointIndex_throwsForNonFiniteInput() {
val underTest = DirectionalMotionSpec.builder(spring).complete()
assertFailsWith<IllegalArgumentException> { underTest.findBreakpointIndex(Float.NaN) }
assertFailsWith<IllegalArgumentException> {
underTest.findBreakpointIndex(Float.NEGATIVE_INFINITY)
}
assertFailsWith<IllegalArgumentException> {
underTest.findBreakpointIndex(Float.POSITIVE_INFINITY)
}
}
@Test
fun findBreakpointIndex_atBreakpoint_returnsIndex() {
val underTest =
DirectionalMotionSpec.builder(spring).toBreakpoint(10f).completeWith(Mapping.Identity)
assertThat(underTest.findBreakpointIndex(10f)).isEqualTo(1)
}
@Test
fun findBreakpointIndex_afterBreakpoint_returnsPreviousIndex() {
val underTest =
DirectionalMotionSpec.builder(spring).toBreakpoint(10f).completeWith(Mapping.Identity)
assertThat(underTest.findBreakpointIndex(10f.nextUp())).isEqualTo(1)
}
@Test
fun findBreakpointIndex_beforeBreakpoint_returnsIndex() {
val underTest =
DirectionalMotionSpec.builder(spring).toBreakpoint(10f).completeWith(Mapping.Identity)
assertThat(underTest.findBreakpointIndex(10f.nextDown())).isEqualTo(0)
}
@Test
fun findBreakpointIndexByKey_returnsIndex() {
val underTest =
DirectionalMotionSpec.builder(spring)
.toBreakpoint(10f, key = b1)
.completeWith(Mapping.Identity)
assertThat(underTest.findBreakpointIndex(b1)).isEqualTo(1)
}
@Test
fun findBreakpointIndexByKey_unknown_returnsMinusOne() {
val underTest =
DirectionalMotionSpec.builder(spring)
.toBreakpoint(10f, key = b1)
.completeWith(Mapping.Identity)
assertThat(underTest.findBreakpointIndex(b2)).isEqualTo(-1)
}
@Test
fun findSegmentIndex_returnsIndexForSegment_ignoringDirection() {
val underTest =
DirectionalMotionSpec.builder(spring)
.toBreakpoint(10f, key = b1)
.continueWith(Mapping.One)
.toBreakpoint(20f, key = b2)
.completeWith(Mapping.Identity)
assertThat(underTest.findSegmentIndex(SegmentKey(b1, b2, InputDirection.Max))).isEqualTo(1)
assertThat(underTest.findSegmentIndex(SegmentKey(b1, b2, InputDirection.Min))).isEqualTo(1)
}
@Test
fun findSegmentIndex_forInvalidKeys_returnsMinusOne() {
val underTest =
DirectionalMotionSpec.builder(spring)
.toBreakpoint(10f, key = b1)
.continueWith(Mapping.One)
.toBreakpoint(20f, key = b2)
.continueWith(Mapping.One)
.toBreakpoint(30f, key = b3)
.completeWith(Mapping.Identity)
assertThat(underTest.findSegmentIndex(SegmentKey(b2, b1, InputDirection.Max))).isEqualTo(-1)
assertThat(underTest.findSegmentIndex(SegmentKey(b1, b3, InputDirection.Max))).isEqualTo(-1)
}
companion object {
val b1 = BreakpointKey("one")
val b2 = BreakpointKey("two")
val b3 = BreakpointKey("three")
val spring = SpringParameters(stiffness = 100f, dampingRatio = 1f)
}
}