feat: add ota and ui changes

This commit is contained in:
TCFDONMEZ
2026-09-29 14:32:25 +03:00
parent c102625306
commit 511c166436
61 changed files with 895 additions and 2178 deletions
@@ -1,52 +0,0 @@
package com.evsuite.abrp;
import org.junit.Test;
import static org.junit.Assert.*;
public class WinCloseDoorSignalTest {
@Test public void firstOpenEventWorksWithoutDrivingOrArming() {
assertTrue(new WinCloseDoorSignal().opening(0));
}
@Test public void repeatedOpenIsIgnoredButAReopeningTriggers() {
WinCloseDoorSignal signal = new WinCloseDoorSignal();
assertFalse(signal.opening(2));
assertTrue(signal.opening(0));
assertFalse(signal.opening(0));
assertFalse(signal.opening(1));
assertFalse(signal.opening(2));
assertTrue(signal.opening(0));
}
@Test public void aSeededOpenDoorIsNotTreatedAsSomeoneOpeningIt() {
WinCloseDoorSignal signal = new WinCloseDoorSignal();
// What a fresh listener registration replays: the door is already open.
signal.seed(0);
assertFalse(signal.opening(0));
// Closing it and opening it again is a real edge.
assertFalse(signal.opening(2));
assertTrue(signal.opening(0));
}
@Test public void seedingAClosedDoorStillArmsTheNextOpening() {
WinCloseDoorSignal signal = new WinCloseDoorSignal();
signal.seed(2);
assertTrue(signal.opening(0));
}
@Test public void seedIgnoresAnInvalidReadingRatherThanRecordingIt() {
WinCloseDoorSignal signal = new WinCloseDoorSignal();
signal.seed(0);
signal.seed(-1);
assertFalse(signal.opening(0));
}
@Test public void invalidReadingDoesNotInventAnotherOpening() {
WinCloseDoorSignal signal = new WinCloseDoorSignal();
assertTrue(signal.opening(0));
assertFalse(signal.opening(-1));
assertFalse(signal.opening(0));
signal.reset();
assertTrue(signal.opening(0));
}
}
@@ -1,53 +0,0 @@
package com.evsuite.abrp;
import org.junit.Test;
import static org.junit.Assert.*;
public class WindowClosePolicyTest {
@Test public void onlyKnownParkAndStandstillCanStart() {
WindowClosePolicy policy = new WindowClosePolicy();
assertFalse(policy.begin(null, 0f));
assertFalse(policy.begin(false, 0f));
assertFalse(policy.begin(true, null));
assertFalse(policy.begin(true, 0.1f));
assertFalse(policy.begin(true, -1f));
assertFalse(policy.begin(true, Float.NaN));
assertFalse(policy.begin(true, Float.POSITIVE_INFINITY));
assertTrue(policy.begin(true, 0f));
}
@Test public void openingsDuringACloseCannotExtendOrQueueIt() {
long[] now = {0L};
WindowClosePolicy policy = new WindowClosePolicy(() -> now[0]);
assertTrue(policy.begin(true, 0f));
assertFalse(policy.begin(true, 0f));
assertFalse(policy.begin(true, 0f));
policy.finish();
// A later, distinct opening needs no previous drive or arming timer.
now[0] += WindowClosePolicy.COOLDOWN_MS;
assertTrue(policy.begin(true, 0f));
}
@Test public void reopeningTheDoorWithinTheCooldownDoesNotCloseAgain() {
long[] now = {0L};
WindowClosePolicy policy = new WindowClosePolicy(() -> now[0]);
assertTrue(policy.begin(true, 0f));
now[0] += 5_000L;
policy.finish();
// Reaching back into the car reopens the door; the glass must not run a second pulse.
now[0] += WindowClosePolicy.COOLDOWN_MS - 1;
assertFalse(policy.begin(true, 0f));
now[0] += 1;
assertTrue(policy.begin(true, 0f));
}
@Test public void theCooldownIsMeasuredFromTheEndOfTheCloseNotItsStart() {
long[] now = {0L};
WindowClosePolicy policy = new WindowClosePolicy(() -> now[0]);
assertTrue(policy.begin(true, 0f));
now[0] += WindowClosePulse.DURATION_MS;
policy.finish();
now[0] += WindowClosePolicy.COOLDOWN_MS - WindowClosePulse.DURATION_MS;
assertFalse(policy.begin(true, 0f));
}
}
@@ -1,84 +0,0 @@
package com.evsuite.abrp;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
public class WindowClosePulseTest {
private final List<String> writes = new ArrayList<>();
private long now;
private boolean send(int area, int command) {
writes.add(area + ":" + command);
return true;
}
private void assertStoppedAll() {
assertEquals(Arrays.asList("0:0", "1:0", "2:0", "3:0"),
writes.subList(writes.size() - 4, writes.size()));
}
@Test public void comfortPulseTargetsAllFourAndEndsAtFiveSeconds() {
assertTrue(WindowClosePulse.run(() -> true, this::send, () -> now, ms -> now += ms));
assertEquals(5_000L, now);
assertEquals(Arrays.asList("0:1", "1:1", "2:1", "3:1"), writes.subList(0, 4));
// Forty-two UP batches at 120 ms intervals, followed by a single STOP batch.
assertEquals(42 * 4 + 4, writes.size());
assertStoppedAll();
}
@Test public void refusedStartWritesNothing() {
assertFalse(WindowClosePulse.run(() -> false, this::send, () -> now, ms -> now += ms));
assertTrue(writes.isEmpty());
}
@Test public void leavingParkMovingOrDisablingStopsAtNextPulse() {
assertFalse(WindowClosePulse.run(() -> now < 120L, this::send, () -> now, ms -> now += ms));
assertEquals(8, writes.size());
assertStoppedAll();
}
@Test public void interruptionReleasesEveryWindowAndPreservesInterrupt() {
try {
assertFalse(WindowClosePulse.run(() -> true, this::send, () -> now,
ms -> { throw new InterruptedException(); }));
assertTrue(Thread.currentThread().isInterrupted());
assertStoppedAll();
} finally {
Thread.interrupted();
}
}
@Test public void oneFailedCommandEndsPulseAndReleasesEveryWindow() {
assertFalse(WindowClosePulse.run(() -> true, (area, command) -> {
send(area, command);
return area != 2 || command == 0;
}, () -> now, ms -> now += ms));
assertEquals(0L, now);
assertStoppedAll();
}
@Test public void unexpectedFailureStillReleasesEveryWindow() {
try {
WindowClosePulse.run(() -> true, (area, command) -> {
send(area, command);
if (area == 1 && command == 1) throw new IllegalStateException();
return true;
}, () -> now, ms -> now += ms);
fail("Expected sender failure");
} catch (IllegalStateException expected) {
assertStoppedAll();
}
}
@Test public void aFailedStopDoesNotPreventOtherStops() {
assertFalse(WindowClosePulse.run(() -> true, (area, command) -> {
send(area, command);
if (area == 0 && command == 0) throw new IllegalStateException();
return true;
}, () -> now, ms -> now += ms));
assertStoppedAll();
}
}