App 2.41.0, server 2.9.0: recordings reach the server

A finished signal recording goes to an outbox and is sent gzipped with
the car's token (PUT /v1/logs/{name}); the service retries every 2
minutes while the car is offline. The server keeps the newest 200 on a
new volume (LOGS_DIR); reading takes a token of its own (LOGS_TOKEN).
fetch-logs in the dev shell fetches new ones into logs/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
2026-10-27 10:22:40 +01:00
co-authored by Claude Opus 5.5
parent 16e6f349da
commit eebe840b6a
20 changed files with 840 additions and 13 deletions
@@ -0,0 +1,45 @@
package com.evsuite.abrp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
public class LogOutboxTest {
@Test
public void whatTheServerSaysDecidesTheFile() {
assertEquals(LogOutbox.Outcome.SENT, LogOutbox.outcome(204));
assertEquals(LogOutbox.Outcome.SENT, LogOutbox.outcome(200));
// Worth another try: no answer, not paired yet, a server without logs yet, busy, broken.
for (int status : new int[] {0, 401, 404, 408, 429, 500, 502, 503}) {
assertEquals(String.valueOf(status), LogOutbox.Outcome.KEEP, LogOutbox.outcome(status));
}
// Refused for good: it would never pass.
for (int status : new int[] {400, 403, 413, 415}) {
assertEquals(String.valueOf(status), LogOutbox.Outcome.DROP, LogOutbox.outcome(status));
}
}
@Test
public void namesAreTheServersKind() {
assertTrue(LogOutbox.validName("signal-recording-20261027-085240.txt"));
assertFalse(LogOutbox.validName("signal-recording-20261027-085240.txt.tmp"));
assertFalse(LogOutbox.validName("../escape.txt"));
assertFalse(LogOutbox.validName("Upper.txt"));
assertFalse(LogOutbox.validName(null));
}
@Test
public void theOldestGoBeyondTheLimit() {
assertEquals(Arrays.asList("signal-recording-20261027-084921.txt"),
LogOutbox.surplus(Arrays.asList("signal-recording-20261027-085240.txt",
"signal-recording-20261027-084921.txt", "signal-recording-20261027-090000.txt"), 2));
assertEquals(Collections.emptyList(),
LogOutbox.surplus(Collections.singletonList("signal-recording-20261027-085240.txt"), 2));
}
}