diff options
Diffstat (limited to 'app/src/test/java/invalid/lena/scrcpy/TouchMapTest.java')
| -rw-r--r-- | app/src/test/java/invalid/lena/scrcpy/TouchMapTest.java | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/app/src/test/java/invalid/lena/scrcpy/TouchMapTest.java b/app/src/test/java/invalid/lena/scrcpy/TouchMapTest.java new file mode 100644 index 0000000..becacc1 --- /dev/null +++ b/app/src/test/java/invalid/lena/scrcpy/TouchMapTest.java @@ -0,0 +1,85 @@ +package invalid.lena.scrcpy; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +// The arithmetic that decides where a tap lands. Until this existed the +// mapping was verified by nothing: the only coverage was an emulator +// self-mirror, where the target and the view are the same size, so the +// transform is the identity and every scaling or offset bug passes. +public class TouchMapTest { + + // A 1080x2400 phone showing a 1080x1920 target: fitted to 864x1920, + // leaving 108px bars left and right. + private static final int VIEW_X = 108, VIEW_W = 864, TARGET_W = 1080; + + @Test + public void leftEdgeOfTheVideoIsTheLeftEdgeOfTheTarget() { + assertEquals(0, TouchMap.map(VIEW_X, VIEW_X, VIEW_W, TARGET_W)); + } + + // The view has fewer pixels than the target, so the last column the + // mapping can produce is floor((span-1) * target / span) - 1078 here, + // not 1079. That is granularity, not an off-by-one: a 864px-wide view + // cannot address all 1080 target columns. What matters is that the + // right edge lands on the last addressable column and stays inside. + @Test + public void rightEdgeIsTheLastAddressableColumn() { + int got = TouchMap.map(VIEW_X + VIEW_W - 1, VIEW_X, VIEW_W, TARGET_W); + assertEquals((VIEW_W - 1) * TARGET_W / VIEW_W, got); + assertTrue("must stay inside the target", got < TARGET_W); + assertTrue("must be within one step of the far edge", + got >= TARGET_W - (TARGET_W / VIEW_W) - 1); + } + + @Test + public void centreMapsToCentre() { + assertEquals(TARGET_W / 2, TouchMap.map(VIEW_X + VIEW_W / 2, VIEW_X, VIEW_W, TARGET_W)); + } + + @Test + public void theLetterboxBarIsClampedNotWrapped() { + // Touches on the bars must land on the near edge. Subtracting the + // origin without clamping would make the left bar negative and the + // right bar overflow past the target's width. + assertEquals(0, TouchMap.map(0, VIEW_X, VIEW_W, TARGET_W)); + assertEquals(0, TouchMap.map(VIEW_X - 50, VIEW_X, VIEW_W, TARGET_W)); + int far = (VIEW_W - 1) * TARGET_W / VIEW_W; // last addressable column + assertEquals(far, TouchMap.map(VIEW_X + VIEW_W + 50, VIEW_X, VIEW_W, TARGET_W)); + assertEquals(far, TouchMap.map(2000, VIEW_X, VIEW_W, TARGET_W)); + } + + @Test + public void neverEscapesTheTargetForAnyCoordinate() { + for (int c = -500; c < 3000; c++) { + int t = TouchMap.map(c, VIEW_X, VIEW_W, TARGET_W); + if (t < 0 || t >= TARGET_W) { + throw new AssertionError("coord " + c + " mapped outside the target: " + t); + } + } + } + + @Test + public void noOverflowAtFourK() { + // 3840 * 2160 exceeds int when multiplied in 32 bits; the mapping + // has to widen before it scales. + assertEquals(2159, TouchMap.map(3839, 0, 3840, 2160)); + assertEquals(0, TouchMap.map(0, 0, 3840, 2160)); + } + + @Test + public void identityWhenTheViewMatchesTheTarget() { + // The self-mirror case the e2e exercises: nothing should move. + for (int c : new int[]{0, 1, 539, 1079}) { + assertEquals(c, TouchMap.map(c, 0, 1080, 1080)); + } + } + + @Test + public void degenerateGeometryIsRefusedRatherThanDividingByZero() { + assertEquals(0, TouchMap.map(100, 0, 0, 1080)); + assertEquals(0, TouchMap.map(100, 0, 1080, 0)); + } +} |