Files
mdg-filius/packages/core/test/programLines.ts
T
julian.kiedaischandClaude Opus 5.5 058675a148 feat(core): the e-mail program after Java, measured against Java
The program sends to its account's SMTP server, one connection for each
recipient, and fetches its mails by POP3; the server now sends mails on
to other domains by MX and returns notices to their senders. The
program's folders are in the snapshot and go back into the project.
EmailClientRun plays six stories with two servers; the mail oracles run
in the language's locale, so Java's notice dates match the core's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 19:38:44 +00:00

136 lines
5.5 KiB
TypeScript

// The lines FILIUS' programs write into their windows, as Java's German
// message bundle says them: for comparing the core's structured lines with
// what the Java oracle recorded (echoJava.test.ts, webJava.test.ts).
import type { EchoServerLogEntry, EmailClientLogEntry, EmailServerLogEntry, PageLanguage, SendFailure, SimpleClientLogEntry, WebBrowserLogEntry } from '../src/index.js';
/** Java's client and server look every 100 ms whether they are connected, or switched off; the core at once. */
export const POLL_MILLISECONDS = 100;
/** Lines Java writes after one of its 100 ms looks. */
const POLLED = new Set(['Verbindung hergestellt', 'Server-Socket geschlossen']);
export const isPolled = (text: string) => POLLED.has(text) || /^Verbindung zu .* hergestellt$/.test(text);
/** sw_tcpsocket_msg6, msg7, msg8. */
export const SEND_FAILURES: Record<SendFailure, string> = {
notConnected: 'Verbindung nicht aufgebaut!',
connectionLost: 'Verbindung wurde unterbrochen',
timedOut: 'Zeitüberschreitung während des Versands einer Nachricht',
};
/** A server's line as Java's window shows it (German message bundle). */
export function serverText(entry: EchoServerLogEntry): string {
switch (entry.kind) {
case 'acceptingStarted':
return 'Annahme von Verbindungsanfragen gestartet';
case 'acceptingStopped':
return 'Annahme von Verbindungsanfragen beendet';
case 'serverSocketClosed':
return 'Server-Socket geschlossen';
case 'serverSocketFailed':
return 'Server-Socket konnte nicht geöffnet werden.';
case 'connectionAccepted':
return `Verbindung zu ${entry.address}:${entry.port} hergestellt`;
case 'received':
return `>>${entry.text}`;
case 'sent':
return `<<${entry.text}`;
case 'sendFailed':
return SEND_FAILURES[entry.failure];
case 'connectionClosed':
return `Socket zu ${entry.address}:${entry.port} geschlossen`;
}
}
export const CONNECT_FAILURES = {
unresolved: 'Ziel konnte nicht bestimmt werden!',
timedOut: 'Zeitüberschreitung beim Verbindungsaufbau',
failed: 'Aktives Öffnen des Sockets fehlgeschlagen',
};
/** A client's line as Java's window shows it. */
export function clientText(entry: SimpleClientLogEntry): string {
switch (entry.kind) {
case 'connected':
return 'Verbindung hergestellt';
case 'connectFailed':
return `Fehler beim Verbindungsaufbau\n${CONNECT_FAILURES[entry.failure]}`;
case 'disconnected':
return 'Verbindung getrennt';
case 'notConnected':
return 'Fehler beim Verbindungsaufbau';
case 'sent':
return `<<${entry.text}`;
case 'received':
return `>>${entry.text}`;
case 'sendFailed':
return SEND_FAILURES[entry.failure];
case 'connectionClosed':
return `Socket zu ${entry.address}:${entry.port} getrennt`;
case 'receiveFailed':
return 'Keine Verbindung hergestellt!';
}
}
const IMAGE_TYPES = new Set(['png', 'gif', 'jpg', 'bmp']);
/** A browser's line as its window took it: a page (with its text only for 200), or "update" for an image. */
export function browserText(entry: WebBrowserLogEntry): string | undefined {
switch (entry.kind) {
case 'page':
return `page ${entry.statusCode} ${entry.contentType ?? 'null'}${entry.statusCode === 200 ? `\n${entry.body ?? 'null'}` : ''}`;
case 'unreachable':
return 'page 0 null';
case 'image': {
// WebBrowser.retrieveImages tells the window of an image that came, or of a status other than 200.
const isImage = entry.contentType !== undefined && IMAGE_TYPES.has(entry.contentType.toLowerCase().replace('image/', ''));
return entry.statusCode !== 200 || isImage ? 'update' : undefined;
}
}
}
/** The e-mail server's line as Java's window shows it (sw_smtpmitarbeiter_msg12 to msg14 in both languages). */
export function emailServerText(entry: EmailServerLogEntry, language: PageLanguage = 'de'): string {
switch (entry.kind) {
case 'connectionOpened':
return '----';
case 'received':
return `${entry.address}< ${entry.text}`;
case 'sent':
return `${entry.address}> ${entry.text}`;
case 'sendFailed':
return language === 'de' ? `Fehler beim Senden an ${entry.address}` : `Error while sending ${entry.address}`;
case 'stored':
return language === 'de' ? `E-Mail für ${entry.username} im Postfach gespeichert.` : `E-mail for ${entry.username} saved in mailbox.`;
default:
return emailClientText(entry);
}
}
/**
* What the SMTP and POP3 clients tell the program they work for, as Java's
* observers get it (sw_smtpclient_msg1 to msg4; a failure as Java's
* exception prints itself; the window shows its message).
*/
export function emailClientText(entry: EmailClientLogEntry): string {
switch (entry.kind) {
case 'connectionStarting':
return '----';
case 'smtpConnected':
return `Verbindung zu ${entry.address}:${entry.port} hergestellt`;
case 'mailSent':
return `Mail versendet an ${entry.recipients}`;
case 'smtpDisconnected':
return `Verbindung zu ${entry.address}:${entry.port} getrennt`;
case 'failed':
switch (entry.failure.kind) {
case 'answer':
return `java.lang.Exception: ${entry.failure.text}`;
case 'connect':
return entry.failure.failure === 'timedOut' ? `filius.exception.TimeOutException: ${CONNECT_FAILURES.timedOut}` : `filius.exception.VerbindungsException: ${CONNECT_FAILURES[entry.failure.failure]}`;
case 'receiveFailed':
return 'filius.exception.VerbindungsException: Verbindung nicht aufgebaut!';
}
}
}