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>
40 lines
1.5 KiB
TypeScript
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();
|
|
});
|
|
});
|