feat(fls): write the file systems of a .fls, loaded by Java as the original
topologyWriter.ts adds each node's file tree to the root its constructor makes, as XMLEncoder does (arbeitsVerzeichnis, files as new Datei(name, typ, inhalt)); a root of its own is set anew. The reader now reads the files of routers and home routers too: their constructor makes files from templates (the web interface), and the file adds to them (a web server's www.conf). systemSoftware.ts keeps what the file adds, and templateFiles says whether the constructor's files stay in front (false when the file sets a root of its own). The topology test finds our part at the end of Java's tree and the template in front, the same for every router of a class across the corpus. Checked by Java against Java: every corpus file, read and written again, loads with the same file systems as the original. The synthetic topology adds a nested tree with a renamed root, a nameless directory, a file without type, content with CR, CRLF and beyond-BMP characters, router files after the template and a home router with a root of its own. 9 mutation probes, each loaded by Java, were all caught. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,8 +12,9 @@
|
||||
// are set through getters. A router's or home router's firewall is reached
|
||||
// the way XMLEncoder reaches it: through the web server's `konfig` plug-in,
|
||||
// which holds the same object (its key among the installed applications
|
||||
// differs: Firewall on a router, NatGateway on a home router). Files and
|
||||
// applications are later layers.
|
||||
// differs: Firewall on a router, NatGateway on a home router). Files are
|
||||
// added to the constructor's root, as XMLEncoder adds them — on a router
|
||||
// after the files its constructor makes. Applications are a later layer.
|
||||
//
|
||||
// Checked by Java: every corpus file, read and written again, loads in Java
|
||||
// FILIUS to the same topology and system software (topologyWriter.test.ts,
|
||||
@@ -31,14 +32,14 @@ import {
|
||||
type BeanValue,
|
||||
short,
|
||||
} from './javaBeansWriter.js';
|
||||
import type { FlsFirewall, FlsSystemSoftware } from './systemSoftware.js';
|
||||
import type { FlsFileTree, FlsFirewall, FlsSystemSoftware } from './systemSoftware.js';
|
||||
import type { FlsDocumentationItem, FlsInterface, FlsLink, FlsNode, FlsNodeClass } from './topology.js';
|
||||
|
||||
/** The version line of the files this writer makes: the format of FILIUS 2.14. */
|
||||
export const WRITTEN_VERSION_LINE = 'Filius version: 2.14.0 (mdg-filius)';
|
||||
|
||||
/** The system software's settings; its files and applications are later layers. */
|
||||
export type SystemToWrite = Omit<FlsSystemSoftware, 'fileSystem' | 'applications'>;
|
||||
/** The system software's settings and files; its applications are a later layer. */
|
||||
export type SystemToWrite = Omit<FlsSystemSoftware, 'applications'>;
|
||||
|
||||
export type NodeToWrite = Pick<
|
||||
FlsNode,
|
||||
@@ -165,6 +166,7 @@ function systemStatements(system: SystemToWrite, javaClass: FlsNodeClass): BeanS
|
||||
],
|
||||
});
|
||||
}
|
||||
if (system.fileSystem !== undefined) statements.push(fileSystemStatement(system.fileSystem, system.templateFiles !== false));
|
||||
if (system.dhcpServer !== undefined) {
|
||||
const server = system.dhcpServer;
|
||||
statements.push({
|
||||
@@ -205,6 +207,35 @@ function systemStatements(system: SystemToWrite, javaClass: FlsNodeClass): BeanS
|
||||
return statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* The file system: the root's children added to the constructor's root
|
||||
* (named "root", empty on a PC or notebook), or a root of its own that
|
||||
* replaces it with the files a router's constructor makes. `arbeitsVerzeichnis`
|
||||
* is the property Java writes; `root` names the same field.
|
||||
*/
|
||||
function fileSystemStatement(root: FlsFileTree, constructedRoot: boolean): BeanStatement {
|
||||
if (!constructedRoot) return { get: 'dateisystem', statements: [{ set: 'arbeitsVerzeichnis', value: treeNode(root) }] };
|
||||
const statements: BeanStatement[] = [];
|
||||
if (!(root.kind === 'directory' && root.name === 'root')) statements.push({ set: 'userObject', value: userObject(root) });
|
||||
statements.push(...childStatements(root));
|
||||
return { get: 'dateisystem', statements: [{ get: 'arbeitsVerzeichnis', statements }] };
|
||||
}
|
||||
|
||||
function childStatements(tree: FlsFileTree): BeanStatement[] {
|
||||
return tree.children.map((child) => ({ call: 'add', args: [treeNode(child)] }));
|
||||
}
|
||||
|
||||
/** A DefaultMutableTreeNode; one of another kind than directory or file is written without a user object. */
|
||||
function treeNode(tree: FlsFileTree): BeanObject {
|
||||
return object('javax.swing.tree.DefaultMutableTreeNode', childStatements(tree), tree.kind === 'other' ? [] : [userObject(tree)]);
|
||||
}
|
||||
|
||||
/** A directory's name, or a file as `new Datei(name, typ, inhalt)`. */
|
||||
function userObject(tree: FlsFileTree): BeanValue {
|
||||
if (tree.kind === 'file') return object('filius.software.system.Datei', [], [tree.name, tree.type, tree.content]);
|
||||
return tree.kind === 'directory' ? tree.name : null;
|
||||
}
|
||||
|
||||
/** A LinkedList of String arrays: routes, static NAT. */
|
||||
function rows(table: readonly (readonly (string | null)[])[]): BeanObject {
|
||||
return listOf(table.map((row) => ({ kind: 'array', componentClass: 'java.lang.String', items: [...row] })));
|
||||
|
||||
Reference in New Issue
Block a user