From 852a8a00273c9128efeed0217a8e5d3fcd8bf780 Mon Sep 17 00:00:00 2001 From: Lena Date: Sat, 1 Aug 2026 00:00:00 +0000 Subject: app: harden mirroring lifecycle and state --- .../test/java/invalid/lena/scrcpy/WireTest.java | 58 ++++++++++++++++------ 1 file changed, 43 insertions(+), 15 deletions(-) (limited to 'app/src/test/java/invalid/lena/scrcpy/WireTest.java') diff --git a/app/src/test/java/invalid/lena/scrcpy/WireTest.java b/app/src/test/java/invalid/lena/scrcpy/WireTest.java index 9cee6c5..e4ada33 100644 --- a/app/src/test/java/invalid/lena/scrcpy/WireTest.java +++ b/app/src/test/java/invalid/lena/scrcpy/WireTest.java @@ -2,15 +2,32 @@ package invalid.lena.scrcpy; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; public class WireTest { + @Test + public void readFullyRejectsZeroProgress() throws Exception { + InputStream in = new InputStream() { + @Override public int read() { return 0; } + @Override public int read(byte[] b, int off, int len) { return 0; } + }; + try { + Wire.readFully(in, new byte[1]); + fail("zero-progress input accepted"); + } catch (IOException expected) { + assertTrue(expected.getMessage().contains("no progress")); + } + } + @Test public void be32RoundTrip() { byte[] b = new byte[4]; @@ -67,28 +84,39 @@ public class WireTest { } } + // Derive the id the way scrcpy's Codec enums do: the ASCII name, right + // aligned in a big-endian uint32, NUL-padded on the left. Deriving it + // from the name is the whole point - the previous version of this test + // asserted the constants against hand-copied literals, so it passed + // while CODEC_AV1 held 'av01' instead of '\0av1' and AV1 could never + // negotiate. + private static int idOf(String name) { + if (name.length() > 4) throw new IllegalArgumentException(name); + int v = 0; + for (int i = 0; i < 4 - name.length(); i++) v <<= 8; + for (int i = 0; i < name.length(); i++) v = (v << 8) | name.charAt(i); + return v; + } + @Test public void fourccConstantsMatchScrcpy() { - // Big-endian uint32 of the 4-char ASCII tag, NUL-padded on the LEFT - // for short names (raw, aac) - mirrors AudioCodec / VideoCodec. - assertEquals(0x68_32_36_34, Wire.CODEC_H264); // "h264" - assertEquals(0x68_32_36_35, Wire.CODEC_H265); // "h265" - assertEquals(0x61_76_30_31, Wire.CODEC_AV1); // "av01" - assertEquals(0x6f_70_75_73, Wire.CODEC_OPUS); // "opus" - assertEquals(0x66_6c_61_63, Wire.CODEC_FLAC); // "flac" - assertEquals(0x00_61_61_63, Wire.CODEC_AAC); // "\0aac" - assertEquals(0x00_72_61_77, Wire.CODEC_RAW); // "\0raw" + // Names as spelled in scrcpy's VideoCodec / AudioCodec enums. + assertEquals(idOf("h264"), Wire.CODEC_H264); + assertEquals(idOf("h265"), Wire.CODEC_H265); + assertEquals(idOf("av1"), Wire.CODEC_AV1); + assertEquals(idOf("opus"), Wire.CODEC_OPUS); + assertEquals(idOf("raw"), Wire.CODEC_RAW); } @Test - public void fourccName() { + public void fourccNameRoundTripsEveryCodec() { assertEquals("h264", Wire.fourccName(Wire.CODEC_H264)); + assertEquals("h265", Wire.fourccName(Wire.CODEC_H265)); + assertEquals("av1", Wire.fourccName(Wire.CODEC_AV1)); assertEquals("opus", Wire.fourccName(Wire.CODEC_OPUS)); + assertEquals("raw", Wire.fourccName(Wire.CODEC_RAW)); + // Left-NUL padding is the rule, not a special case for raw. + assertEquals("aac", Wire.fourccName(0x00_61_61_63)); } - @Test - public void fourccNameTrimsLeadingNuls() { - assertEquals("raw", Wire.fourccName(Wire.CODEC_RAW)); - assertEquals("aac", Wire.fourccName(Wire.CODEC_AAC)); - } } -- cgit v1.2.3