Prd/components/dialer-patch/tests/CommandGateTest.java
Lucy Doupalů be9f14ce34 Helpdesk - operator console + patched GrapheneOS Dialer for call handling
A small helpdesk system: an office Pixel running a patched GrapheneOS Dialer
answers technician calls, records both call legs as separate channels, and a
Ruby backend transcribes them through Whisper and files an AI summary against
the caller.

Squashed to a single commit for sharing. No credentials are included; secrets
live outside the repo in /etc/helpdesk/env on the server or a gitignored
.claude/env.local locally. See .claude/env.local.example for the shape.

Start at README.md, then docs/architecture.md.
2026-07-27 18:50:32 +02:00

72 lines
3.6 KiB
Java

package com.android.dialer.helpdesk.command;
import static com.android.dialer.helpdesk.command.CommandGate.CallPhase.ACTIVE;
import static com.android.dialer.helpdesk.command.CommandGate.CallPhase.ENDED;
import static com.android.dialer.helpdesk.command.CommandGate.CallPhase.RINGING;
import static com.android.dialer.helpdesk.command.CommandGate.Decision.APPLY;
import static com.android.dialer.helpdesk.command.CommandGate.Decision.DROP_BAD_ARG;
import static com.android.dialer.helpdesk.command.CommandGate.Decision.DROP_DUPLICATE;
import static com.android.dialer.helpdesk.command.CommandGate.Decision.DROP_STALE;
import static com.android.dialer.helpdesk.command.CommandGate.Decision.DROP_UNKNOWN_VERB;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Standalone off-device test for {@link CommandGate}. Modes:
* - default: decision assertions.
* - "verbs": print the sorted verb set (harness diffs vs Helpdesk::COMMAND_VERBS).
* - "dtmf": read args from stdin, print valid/invalid (harness diffs vs valid_dtmf?).
*/
public class CommandGateTest {
static int pass = 0, fail = 0;
static void eq(Object got, Object want, String d) {
if (got == null ? want == null : got.equals(want)) { pass++; System.out.println(" ok " + d); }
else { fail++; System.out.println(" FAIL " + d + " (got: " + got + ")"); }
}
public static void main(String[] args) throws Exception {
if (args.length > 0 && args[0].equals("verbs")) {
List<String> v = new ArrayList<>(CommandGate.VERBS);
Collections.sort(v);
for (String s : v) System.out.println(s);
return;
}
if (args.length > 0 && args[0].equals("dtmf")) {
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = r.readLine()) != null) {
System.out.println(CommandGate.isValidDtmf(line) ? "valid" : "invalid");
}
return;
}
CommandGate g = new CommandGate();
eq(g.decide("1", "answer", null, RINGING), APPLY, "answer on ringing applies");
eq(g.decide("1", "answer", null, RINGING), DROP_DUPLICATE, "same id dropped (idempotent)");
eq(g.decide("2", "answer", null, ENDED), DROP_STALE, "answer on ended dropped (monotonic)");
eq(g.decide("3", "explode", null, RINGING), DROP_UNKNOWN_VERB, "unknown verb dropped");
eq(g.decide("4", "dtmf", "5", ACTIVE), APPLY, "valid dtmf applies");
eq(g.decide("5", "dtmf", "X", ACTIVE), DROP_BAD_ARG, "bad dtmf arg dropped");
eq(g.decide("6", "dtmf", "#", ACTIVE), APPLY, "'#' is a valid dtmf");
eq(g.decide("7", "mute", null, ACTIVE), APPLY, "mute applies mid-call");
eq(g.decide("8", "hangup", null, ACTIVE), APPLY, "hangup applies mid-call");
eq(g.decide("9", "route", "bluetooth", ACTIVE), APPLY, "route applies");
// a bad command is never recorded as seen -> a corrected retry with the same id still evaluates
eq(g.decide("3", "answer", null, RINGING), APPLY, "id reused after prior unknown-verb still applies");
// bounded seen set (no unbounded growth over a long-running service) + per-call reset
CommandGate g2 = new CommandGate();
for (int i = 0; i < CommandGate.MAX_SEEN + 500; i++) {
g2.decide("id" + i, "mute", null, ACTIVE);
}
eq(g2.seenSize() <= CommandGate.MAX_SEEN, true, "seen set bounded at MAX_SEEN (no leak)");
g2.reset();
eq(g2.seenSize(), 0, "reset() clears dedup memory (per-call scope)");
eq(g2.decide("id0", "mute", null, ACTIVE), APPLY, "id re-applies after reset()");
System.out.println("\n" + pass + " passed, " + fail + " failed");
System.exit(fail == 0 ? 0 : 1);
}
}