The Java view now reads what FILIUS 2.14 keeps for its e-mail programs: the server's domain, switch and bean accounts with their mailboxes, and the accounts of /mailserver/konten.txt, which Java reads at every simulation start and which so win over the bean list; the client's three folders and address book, and its account from /konten.txt (no bean holds it). javaEmail.ts ports the bean setters and both file readers (stringZuListeBenutzerkonten, EmailKonto(String)); javaString.ts Java's trim, split and StringTokenizer; javaFileSystem.ts the file lookup, now shared with the DNS server, with the four non-ASCII units Java's equalsIgnoreCase also takes for an ASCII letter (measured over the BMP). Checked against Java on the corpus (the oracle dumps the e-mail state) and on 43 account files read by EmailServer.kontenLaden and EmailAnwendung.laden (EmailFileCases). Found: older files keep recipients as strings in the typed lists; a getter copy of the sender is filled and set back; one short server line makes Java throw for the whole file; a message with an empty text is lost on reading; a broken last client line empties the account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
2.5 KiB
TypeScript
56 lines
2.5 KiB
TypeScript
// Java's readers of the e-mail account files: every case in
|
|
// email-server.cases.txt and email-client.cases.txt was read by Java
|
|
// (EmailServer.kontenLaden, EmailAnwendung.laden; *.java.json,
|
|
// tools/java-oracle) and must come out the same here.
|
|
|
|
import { readFileSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { addressEntry, readJavaEmailClientFile, readJavaEmailServerFile } from '../src/javaEmail.js';
|
|
import { javaEmailAccount } from './javaEmailNames.js';
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
|
|
/** The cases file's escapes: a backslash, `u` and four hex digits for one UTF-16 unit. */
|
|
function unescape(line: string): string {
|
|
return line.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex: string) => String.fromCharCode(Number.parseInt(hex, 16)));
|
|
}
|
|
|
|
function measured(kind: 'server' | 'client'): [string, unknown][] {
|
|
const cases = JSON.parse(readFileSync(join(here, `email-${kind}.java.json`), 'utf8')) as [string, unknown][];
|
|
const lines = readFileSync(join(here, `email-${kind}.cases.txt`), 'ascii').split('\n').slice(0, -1);
|
|
it('covers every line of the cases file', () => {
|
|
expect(cases.map(([line]) => line)).toEqual(lines);
|
|
});
|
|
return cases;
|
|
}
|
|
|
|
describe('readJavaEmailServerFile against Java', () => {
|
|
for (const [line, expected] of measured('server')) {
|
|
it(JSON.stringify(line), () => {
|
|
const accounts = readJavaEmailServerFile(unescape(line));
|
|
expect(Array.isArray(accounts) ? accounts.map(javaEmailAccount) : `!${accounts.exception}`).toEqual(expected);
|
|
});
|
|
}
|
|
});
|
|
|
|
describe('readJavaEmailClientFile against Java', () => {
|
|
for (const [line, expected] of measured('client')) {
|
|
it(JSON.stringify(line), () => {
|
|
const account = readJavaEmailClientFile(unescape(line));
|
|
expect(account === null ? null : javaEmailAccount(account)).toEqual(expected);
|
|
});
|
|
}
|
|
});
|
|
|
|
describe('addressEntry', () => {
|
|
it('reads a name and an address, an address alone, or a name alone', () => {
|
|
expect(addressEntry(' Alice <alice@senior.de> ')).toEqual({ name: 'Alice', mailAddress: 'alice@senior.de' });
|
|
expect(addressEntry('<alice@senior.de>')).toEqual({ name: null, mailAddress: 'alice@senior.de' });
|
|
expect(addressEntry('alice@senior.de')).toEqual({ name: null, mailAddress: 'alice@senior.de' });
|
|
expect(addressEntry('Alice <alice@senior.de')).toEqual({ name: 'Alice <alice@senior.de', mailAddress: null });
|
|
expect(addressEntry('Alice')).toEqual({ name: 'Alice', mailAddress: null });
|
|
});
|
|
});
|