diff --git a/android/app/src/test/java/com/openipc/decoder/JieliTest.java b/android/app/src/test/java/com/openipc/decoder/JieliTest.java index 0576f43..e3d460a 100644 --- a/android/app/src/test/java/com/openipc/decoder/JieliTest.java +++ b/android/app/src/test/java/com/openipc/decoder/JieliTest.java @@ -799,7 +799,9 @@ public void noVideoListensElsewhereAndAsksAgain() throws Exception { Jieli.noVideoMs = 300; Jieli.reopenMs = 700; Jieli.diagnosticPorts = new int[] {diag}; - Jieli.diagnosticMs = 500; + // The port lives this long (then up to a receive timeout more): long enough for the + // packet below to arrive on a loaded CI runner, where a pause of a second failed it (#257) + Jieli.diagnosticMs = 3000; try (FakeToy toy = new FakeToy(60000, true)) { toy.rtpPort = rtp; toy.sendVideo = false; @@ -813,13 +815,16 @@ public void noVideoListensElsewhereAndAsksAgain() throws Exception { byte[] p = {(byte) 0x80, 97, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 9}; u.send(new DatagramPacket(p, p.length, new InetSocketAddress(LOOPBACK, diag))); } - until = now() + 3000; + // Generous on a loaded runner; the asserts read the snapshot the loop stopped on + // (Qodo on #259) + until = now() + 8000; + Map st = r.client.stats(); while (now() < until && (Collections.frequency(toy.topics(), Jieli.OPEN_RT_STREAM) < 2 - || r.client.stats().get("diagnostic_ports") == null)) { + || st.get("diagnostic_ports") == null)) { Thread.sleep(20); + st = r.client.stats(); } assertTrue(Collections.frequency(toy.topics(), Jieli.OPEN_RT_STREAM) >= 2); - Map st = r.client.stats(); @SuppressWarnings("unchecked") Map d = (Map) st.get("diagnostic_ports"); assertNotNull(d); @@ -827,7 +832,7 @@ public void noVideoListensElsewhereAndAsksAgain() throws Exception { Map one = (Map) d.get(String.valueOf(diag)); assertEquals(1, one.get("packets")); // The diagnostic port is freed after diagnosticMs while the session goes on - until = now() + 3000; + until = now() + 6000; boolean freed = false; while (now() < until && !freed) { try (DatagramSocket again = new DatagramSocket(diag, LOOPBACK)) { diff --git a/android/app/src/test/java/com/openipc/decoder/RtpListenerTest.java b/android/app/src/test/java/com/openipc/decoder/RtpListenerTest.java index bcf8cfb..34636b9 100644 --- a/android/app/src/test/java/com/openipc/decoder/RtpListenerTest.java +++ b/android/app/src/test/java/com/openipc/decoder/RtpListenerTest.java @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -101,9 +102,11 @@ public void badUrlsAreRefused() { // ====================== Session ====================== private static final class Recorder implements RtspSession.Callback { - final List statuses = Collections.synchronizedList(new ArrayList<>()); - final List sdps = Collections.synchronizedList(new ArrayList<>()); - final List pts = Collections.synchronizedList(new ArrayList<>()); + // Filled by the session thread while the test reads them: Collections.frequency() and + // for-each iterate, which a synchronizedList does not guard (#257) + final List statuses = new CopyOnWriteArrayList<>(); + final List sdps = new CopyOnWriteArrayList<>(); + final List pts = new CopyOnWriteArrayList<>(); volatile CountDownLatch latch = new CountDownLatch(3); @Override public void onStatus(String status) { statuses.add(status); }