feat(fls): Java's view of the e-mail programs
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>
This commit is contained in:
@@ -18,8 +18,11 @@ import {
|
||||
type FlsModem,
|
||||
type FlsNodeClass,
|
||||
type FlsTopology,
|
||||
type JavaEmailAccount,
|
||||
type JavaFailure,
|
||||
} from '../src/index.js';
|
||||
import { EXPECTED_WARNINGS } from './expectedWarnings.js';
|
||||
import { javaEmail, javaEmailAccount } from './javaEmailNames.js';
|
||||
|
||||
const corpusRoot = join(dirname(fileURLToPath(import.meta.url)), '../../../corpus');
|
||||
const javaView = JSON.parse(readFileSync(join(corpusRoot, 'corpus.java.json'), 'utf8')) as Record<string, unknown>;
|
||||
@@ -91,9 +94,39 @@ function javaApplications(applications: FlsApplication[]): unknown[] {
|
||||
filterUdp: application.firewall.filterUdp,
|
||||
rules: application.firewall.rules.length,
|
||||
}),
|
||||
...(application.mailDomain === undefined
|
||||
? {}
|
||||
: {
|
||||
mailDomain: application.mailDomain,
|
||||
beanAccounts: application.beanAccounts!.map(javaEmailAccount),
|
||||
fileAccounts: javaFileAccounts(application.fileAccounts!),
|
||||
}),
|
||||
...(application.received === undefined
|
||||
? {}
|
||||
: {
|
||||
received: application.received.map(javaEmail),
|
||||
sent: application.sent!.map(javaEmail),
|
||||
drafts: application.drafts!.map(javaEmail),
|
||||
addressBook: application.addressBook!.map((contact) => [
|
||||
contact.name,
|
||||
contact.firstName,
|
||||
contact.street,
|
||||
contact.houseNumber,
|
||||
contact.postalCode,
|
||||
contact.city,
|
||||
contact.email,
|
||||
contact.phone,
|
||||
]),
|
||||
fileAccount: application.fileAccount === null ? null : javaEmailAccount(application.fileAccount!),
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
||||
function javaFileAccounts(accounts: JavaEmailAccount[] | JavaFailure | null): unknown {
|
||||
if (accounts === null) return null;
|
||||
return Array.isArray(accounts) ? accounts.map(javaEmailAccount) : `!${accounts.exception}`;
|
||||
}
|
||||
|
||||
/** Java's property names, as FlsOracle.java writes them. */
|
||||
function javaDhcpServer(server: FlsDhcpServer) {
|
||||
return {
|
||||
@@ -423,6 +456,29 @@ describe('readTopology rules', () => {
|
||||
expect(Object.keys(byClass.get('filius.software.lokal.Terminal')!).sort()).toEqual(['javaClass', 'key', 'source']);
|
||||
});
|
||||
|
||||
it('reads the e-mail beans through their setters: null names, string senders, a checked domain', () => {
|
||||
const put = (className: string, body = '') =>
|
||||
`<void method="put"><string>${className}</string><object class="${className}">${body}</object></void>`;
|
||||
const { nodes } = topologyOf(`<object class="java.util.LinkedList">${nodeItem(`<object class="filius.hardware.knoten.Rechner">
|
||||
<void property="systemSoftware"><void property="installierteAnwendungen">
|
||||
${put('filius.software.email.EmailServer', `
|
||||
<void property="mailDomain"><string>1und1.de</string></void>
|
||||
<void property="listeBenutzerkonten"><void method="add"><object class="filius.software.email.EmailKonto">
|
||||
<void property="benutzername"><string>bob</string></void>
|
||||
<void property="nachname"><null/></void>
|
||||
<void property="nachrichten"><void method="add"><object class="filius.software.email.Email">
|
||||
<void property="absender"><string> Alice <alice@senior.de> </string></void>
|
||||
</object></void></void>
|
||||
</object></void></void>`)}
|
||||
</void></void></object>`)}</object>`);
|
||||
const server = nodes[0]!.system.applications![0]!;
|
||||
|
||||
// setMailDomain keeps "filius.de" for a domain Java's pattern rejects.
|
||||
expect(server).toMatchObject({ isActive: false, mailDomain: 'filius.de' });
|
||||
expect(server.beanAccounts![0]).toMatchObject({ username: 'bob', lastName: '', firstName: '' });
|
||||
expect(server.beanAccounts![0]!.messages[0]!.sender).toEqual({ name: 'Alice', mailAddress: 'alice@senior.de' });
|
||||
});
|
||||
|
||||
it("gives a modem Java's defaults and keeps an address the file sets to null", () => {
|
||||
const { nodes } = topologyOf(`<object class="java.util.LinkedList">
|
||||
${nodeItem('<object class="filius.hardware.knoten.Modem"/>')}
|
||||
|
||||
Reference in New Issue
Block a user