Files
mdg-filius/packages/fls/test/javaIp.test.ts
T
julian.kiedaischandClaude Opus 5.5 a4036f12a3 feat(core): RIP after Java's code
Where the Swift template departs from Java's filius.software.rip, Java's
code rules: a learned route gets 16 hops at the router's next beacon after
it expired (RIPTable.check), not when it expires; messages count from any
source port; each router draws its pauses from a random of its own (Java:
an unseeded Random per router), which the core seeds from the scenario and
the router's id (ripSeed), so that the Java oracle can give it the same.

A route of hop count 0 to each own network, the first beacon after a
second, then every 25.2 to 35.2 s; a message per interface without the
routes through it; a new route or a longer one from the same router sends
at once; forwarding by the table alone, fewest hops before longest mask.
Messages are read with Java's parser (javaIpCheck, javaParseInt, moved from
fls to core for it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 19:29:48 +00:00

40 lines
1.5 KiB
TypeScript

// IP.ipCheck as Java FILIUS runs it: every case in ip-check.cases.txt was run
// through Java (ip-check.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 { javaIpCheck, javaParseInt } from '@mdg-filius/core';
const here = dirname(fileURLToPath(import.meta.url));
const measured = JSON.parse(readFileSync(join(here, 'ip-check.java.json'), 'utf8')) as [string, string | null][];
/** 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)));
}
describe('javaIpCheck against Java', () => {
it('covers every line of the cases file', () => {
const lines = readFileSync(join(here, 'ip-check.cases.txt'), 'ascii').split('\n').slice(0, -1);
expect(measured.map(([line]) => line)).toEqual(lines);
});
for (const [line, expected] of measured) {
it(JSON.stringify(line), () => {
expect(javaIpCheck(unescape(line))).toBe(expected);
});
}
});
describe('javaParseInt', () => {
it('keeps to the int range', () => {
expect(javaParseInt('2147483647')).toBe(2147483647);
expect(javaParseInt('-2147483648')).toBe(-2147483648);
expect(javaParseInt('2147483648')).toBeUndefined();
expect(javaParseInt('-2147483649')).toBeUndefined();
});
});