test: F2 acceptance — five of FILIUS' examples run as Java FILIUS runs them
ExampleRun opens an example as FILIUS opens it (SzenarioVerwaltung.laden into the window's lists), starts it as the action mode does, plays a story and writes every card's frames and tables, the calls, the addresses and the RIP tables' changes. examplesJava.test.ts reads the same file with this package's reader and runs it in the core (projectSnapshot, new): routing (internetwork_komplett), DHCP (einfaches_rechnernetz_komplett), DNS (dns_server), NAT (nat_with_mapped_port) and firewall (Internet_Komplett_..._DE) match card by card. Found and fixed: a host's ipForwardingEnabled, which Java saves and obeys, was unknown to the reader, the model, the core, the writer, the export and FlsOracle; and Java's ARP learns only from a request for its own address or a reply. Named Java bugs: a ping without a gateway throws a NullPointerException; a home router drops the answer of a second remote end. Open: Java picks between equally long RIP routes by thread timing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,7 +96,7 @@ const FLAG_LETTERS: [number, string][] = [
|
||||
[TCP_FLAG.reset, 'R'],
|
||||
];
|
||||
|
||||
function engineText(frame: EthernetFrame): string {
|
||||
export function engineText(frame: EthernetFrame): string {
|
||||
const macs = `${frame.sourceMacAddress} > ${frame.destinationMacAddress}`.toUpperCase();
|
||||
if (frame.payload.kind === 'arp') {
|
||||
const arp = frame.payload.packet;
|
||||
@@ -146,14 +146,14 @@ export function watchedEngine(scenario: Scenario) {
|
||||
}
|
||||
|
||||
/** Java's frames of all cards, each once: the same text within the window is the same frame. */
|
||||
export function javaFrames(framesByNode: Record<string, JavaFrame[]>): SeenFrame[] {
|
||||
export function javaFrames(framesByNode: Record<string, JavaFrame[]>, windowMilliseconds = DUPLICATE_WINDOW_MILLISECONDS): SeenFrame[] {
|
||||
const all = Object.values(framesByNode)
|
||||
.flat()
|
||||
.map((frame) => ({ time: frame.time, text: javaText(frame) }))
|
||||
.sort((lhs, rhs) => lhs.time - rhs.time);
|
||||
const frames: SeenFrame[] = [];
|
||||
for (const frame of all) {
|
||||
if (frames.some((each) => each.text === frame.text && frame.time - each.time <= DUPLICATE_WINDOW_MILLISECONDS)) continue;
|
||||
if (frames.some((each) => each.text === frame.text && frame.time - each.time <= windowMilliseconds)) continue;
|
||||
frames.push(frame);
|
||||
}
|
||||
return frames;
|
||||
@@ -174,9 +174,22 @@ export function gaps(frames: readonly SeenFrame[]) {
|
||||
* `normalized` does so for a card's whole list; with `until` (Java's time),
|
||||
* only the frames before it; with `from`, only those from it.
|
||||
*/
|
||||
/** A card to compare: the key Java's lists have it under, and its port in the engine. */
|
||||
export interface CaptureCard {
|
||||
readonly key: string;
|
||||
readonly portId: string;
|
||||
}
|
||||
|
||||
/** A scenario's cards: its hosts' ports, under the node's id for the first card and `id#index` for the others (ScenarioNetwork). */
|
||||
export function scenarioCards(scenario: Scenario): CaptureCard[] {
|
||||
return scenario.nodes
|
||||
.filter((node) => node.kind !== 'networkSwitch')
|
||||
.flatMap((node) => node.ports.map((port, index) => ({ key: index === 0 ? node.id : `${node.id}#${index}`, portId: port.id })));
|
||||
}
|
||||
|
||||
export function expectSameCaptures(
|
||||
engine: NetworkRuntimeEngine,
|
||||
scenario: Scenario,
|
||||
cardsOrScenario: Scenario | readonly CaptureCard[],
|
||||
java: Record<string, JavaFrame[]>,
|
||||
options: {
|
||||
text?: (text: string) => string;
|
||||
@@ -194,13 +207,10 @@ export function expectSameCaptures(
|
||||
const text = options.text ?? ((each: string) => each);
|
||||
const engineByCard = new Map<string, SeenFrame[]>();
|
||||
const capturedByCard = new Map<string, readonly CapturedFrame[]>();
|
||||
for (const node of scenario.nodes) {
|
||||
if (node.kind === 'networkSwitch') continue;
|
||||
node.ports.forEach((port, index) => {
|
||||
const card = index === 0 ? node.id : `${node.id}#${index}`;
|
||||
capturedByCard.set(card, engine.capture.frames(port.id));
|
||||
engineByCard.set(card, capturedByCard.get(card)!.map((each) => ({ time: each.timeMilliseconds, text: text(engineText(each.frame)) })));
|
||||
});
|
||||
const cards = 'nodes' in cardsOrScenario ? scenarioCards(cardsOrScenario) : cardsOrScenario;
|
||||
for (const { key, portId } of cards) {
|
||||
capturedByCard.set(key, engine.capture.frames(portId));
|
||||
engineByCard.set(key, capturedByCard.get(key)!.map((each) => ({ time: each.timeMilliseconds, text: text(engineText(each.frame)) })));
|
||||
}
|
||||
const javaByCard = new Map(Object.entries(java).map(([card, frames]) => [card, frames.map((frame) => ({ time: frame.time, text: text(javaText(frame)) }))]));
|
||||
expect([...engineByCard.keys()].sort()).toEqual([...javaByCard.keys()].sort());
|
||||
|
||||
Reference in New Issue
Block a user