feat(fls): read and write a project's own applications as their beans
A project's own applications (classes under projekt/anwendungen, installed on a host) are no longer left out. The decoder now keeps the Java type of every primitive — at setters, constructor and call arguments, also through shared ids like Integer0 — and which properties an object's own getter made. beanCapture.ts turns a decoded bean back into what the writer writes, with the node's system software as a mark the writer replaces by the system software it writes; what the format cannot say is refused, not guessed (an unresolved value, a Field, a factory-made object, an object a getter reaches elsewhere in the file). The reader keeps own applications as captured beans; the corpus no longer warns. The capture first took a setter with another object's getter result for an own getter; the round-trip test found it. The Java oracle did not show whether an application runs on its node's system software, so a mutation writing the mark instead survived; it now reports onItsSystem (true for all 192 applications of the corpus). Checked by Java: from the files written again, FILIUS loads Accumulator and Broadcast installed, switched on and on their node's system software, as in the original. The round-trip test covers every primitive, null, a class, an array, shared objects, getter chains, constructed elements, map reads and static constants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,6 @@ import { describe, expect, it } from 'vitest';
|
||||
import { decodeJavaBeans, readFlsArchive, readTopology, writeFlsArchive } from '../src/index.js';
|
||||
import type { JavaEmail } from '../src/javaEmail.js';
|
||||
import { writeTopologyXml, type TopologyToWrite } from '../src/topologyWriter.js';
|
||||
import { withoutOwnApplications } from './ownApplications.js';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const corpusRoot = join(here, '../../../corpus');
|
||||
@@ -94,8 +93,10 @@ describe('the topology written again, as Java loads it', () => {
|
||||
for (const file of flsFiles(corpusRoot)) {
|
||||
const name = relative(corpusRoot, file);
|
||||
it(name, () => {
|
||||
const topology = readTopology(decodeJavaBeans(readFlsArchive(new Uint8Array(readFileSync(file))).configurationXml));
|
||||
const archive = writeFlsArchive(new TextEncoder().encode(writeTopologyXml(topology)));
|
||||
const contents = readFlsArchive(new Uint8Array(readFileSync(file)));
|
||||
const topology = readTopology(decodeJavaBeans(contents.configurationXml));
|
||||
// With the archive's other entries: the classes of the project's own applications.
|
||||
const archive = writeFlsArchive(new TextEncoder().encode(writeTopologyXml(topology)), contents.supplementalEntries);
|
||||
if (process.env.UPDATE_WRITTEN === '1') {
|
||||
mkdirSync(dirname(join(writtenRoot, name)), { recursive: true });
|
||||
writeFileSync(join(writtenRoot, name), archive);
|
||||
@@ -104,8 +105,7 @@ describe('the topology written again, as Java loads it', () => {
|
||||
expect(java?.sha256, 'written.java.json is not about this output: UPDATE_WRITTEN=1, then npm run oracle:java').toBe(
|
||||
createHash('sha256').update(archive).digest('hex'),
|
||||
);
|
||||
// The written file has no archive entries: Java installs no own application (B2).
|
||||
expect(topologyOf(java!)).toEqual(topologyOf(withRecipientsRead(withoutOwnApplications(original[name]!)) as JavaFile));
|
||||
expect(topologyOf(java!)).toEqual(topologyOf(withRecipientsRead(original[name]!) as JavaFile));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -448,13 +448,13 @@ describe('a topology beyond the corpus, as Java loads it', () => {
|
||||
},
|
||||
// In the order of Java's key.
|
||||
applications: [
|
||||
{ key: 'filius.software.clientserver.ClientBaustein', class: 'filius.software.clientserver.ClientBaustein', zielIPAdresse: '10.0.0.9', zielPort: 7777 },
|
||||
{ key: 'filius.software.clientserver.ServerBaustein', class: 'filius.software.clientserver.ServerBaustein', aktiv: true, port: 7777 },
|
||||
{ key: 'filius.software.dateiaustausch.PeerToPeerAnwendung', class: 'filius.software.dateiaustausch.PeerToPeerAnwendung', maxTeilnehmerZahl: 7 },
|
||||
{ key: 'filius.software.dns.DNSServer', class: 'filius.software.dns.DNSServer', aktiv: true, port: 5353, recursiveResolutionEnabled: true },
|
||||
{ key: 'filius.software.clientserver.ClientBaustein', class: 'filius.software.clientserver.ClientBaustein', onItsSystem: true, zielIPAdresse: '10.0.0.9', zielPort: 7777 },
|
||||
{ key: 'filius.software.clientserver.ServerBaustein', class: 'filius.software.clientserver.ServerBaustein', onItsSystem: true, aktiv: true, port: 7777 },
|
||||
{ key: 'filius.software.dateiaustausch.PeerToPeerAnwendung', class: 'filius.software.dateiaustausch.PeerToPeerAnwendung', onItsSystem: true, maxTeilnehmerZahl: 7 },
|
||||
{ key: 'filius.software.dns.DNSServer', class: 'filius.software.dns.DNSServer', onItsSystem: true, aktiv: true, port: 5353, recursiveResolutionEnabled: true },
|
||||
{
|
||||
key: 'filius.software.email.EmailAnwendung',
|
||||
class: 'filius.software.email.EmailAnwendung',
|
||||
class: 'filius.software.email.EmailAnwendung', onItsSystem: true,
|
||||
received: [javaMail()],
|
||||
sent: [javaMail({ versendet: true, neu: false })],
|
||||
drafts: [javaMail({ betreff: null, text: null, dateReceived: null, empfaenger: [] })],
|
||||
@@ -464,7 +464,7 @@ describe('a topology beyond the corpus, as Java loads it', () => {
|
||||
},
|
||||
{
|
||||
key: 'filius.software.email.EmailServer',
|
||||
class: 'filius.software.email.EmailServer',
|
||||
class: 'filius.software.email.EmailServer', onItsSystem: true,
|
||||
aktiv: true,
|
||||
mailDomain: 'schule.de',
|
||||
beanAccounts: [
|
||||
@@ -486,7 +486,7 @@ describe('a topology beyond the corpus, as Java loads it', () => {
|
||||
},
|
||||
{
|
||||
key: 'filius.software.firewall.Firewall',
|
||||
class: 'filius.software.firewall.Firewall',
|
||||
class: 'filius.software.firewall.Firewall', onItsSystem: true,
|
||||
activated: false,
|
||||
defaultPolicy: 1,
|
||||
dropICMP: true,
|
||||
@@ -494,12 +494,12 @@ describe('a topology beyond the corpus, as Java loads it', () => {
|
||||
filterUdp: false,
|
||||
rules: [['10.0.0.0', '255.0.0.0', '', '', 22, 6, 1]],
|
||||
},
|
||||
{ key: 'filius.software.lokal.FileExplorer', class: 'filius.software.lokal.FileExplorer' },
|
||||
{ key: 'filius.software.lokal.ImageViewer', class: 'filius.software.lokal.ImageViewer' },
|
||||
{ key: 'filius.software.lokal.Terminal', class: 'filius.software.lokal.Terminal' },
|
||||
{ key: 'filius.software.lokal.TextEditor', class: 'filius.software.lokal.TextEditor' },
|
||||
{ key: 'filius.software.www.WebBrowser', class: 'filius.software.www.WebBrowser' },
|
||||
{ key: 'filius.software.www.WebServer', class: 'filius.software.www.WebServer', aktiv: true, port: 8080, useVHost: true },
|
||||
{ key: 'filius.software.lokal.FileExplorer', class: 'filius.software.lokal.FileExplorer', onItsSystem: true },
|
||||
{ key: 'filius.software.lokal.ImageViewer', class: 'filius.software.lokal.ImageViewer', onItsSystem: true },
|
||||
{ key: 'filius.software.lokal.Terminal', class: 'filius.software.lokal.Terminal', onItsSystem: true },
|
||||
{ key: 'filius.software.lokal.TextEditor', class: 'filius.software.lokal.TextEditor', onItsSystem: true },
|
||||
{ key: 'filius.software.www.WebBrowser', class: 'filius.software.www.WebBrowser', onItsSystem: true },
|
||||
{ key: 'filius.software.www.WebServer', class: 'filius.software.www.WebServer', onItsSystem: true, aktiv: true, port: 8080, useVHost: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user