111 lines
4.4 KiB
JavaScript
111 lines
4.4 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mkdtempSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { loadGeo } from '../src/geo.js';
|
|
|
|
const CSV = [
|
|
'1.0.0.0,1.0.0.255,AU',
|
|
'5.9.0.0,5.9.255.255,DE',
|
|
'5.10.0.0,5.10.0.9,ZZ',
|
|
'8.8.8.0,8.8.8.255,US',
|
|
'255.255.255.0,255.255.255.255,FR',
|
|
'2001:db8::,2001:db8:ffff:ffff:ffff:ffff:ffff:ffff,AT',
|
|
'2a01:4f8::,2a01:4f8:ffff:ffff:ffff:ffff:ffff:ffff,DE',
|
|
'2a02:1::1,2a02:1::ff,CH',
|
|
'',
|
|
].join('\n');
|
|
|
|
function fixture(content) {
|
|
const dir = mkdtempSync(join(tmpdir(), 'geo-'));
|
|
const f = join(dir, 'geo.csv');
|
|
writeFileSync(f, content);
|
|
return f;
|
|
}
|
|
|
|
test('IPv4: Treffer und Grenzen', () => {
|
|
const g = loadGeo(fixture(CSV));
|
|
assert.equal(g.size, 8);
|
|
assert.equal(g.lookup('5.9.0.0'), 'DE');
|
|
assert.equal(g.lookup('5.9.123.4'), 'DE');
|
|
assert.equal(g.lookup('5.9.255.255'), 'DE');
|
|
assert.equal(g.lookup('5.8.255.255'), '');
|
|
assert.equal(g.lookup('5.10.0.0'), '');
|
|
assert.equal(g.lookup('1.0.0.255'), 'AU');
|
|
assert.equal(g.lookup('1.0.1.0'), '');
|
|
assert.equal(g.lookup('0.0.0.1'), '');
|
|
assert.equal(g.lookup('255.255.255.255'), 'FR');
|
|
assert.equal(g.lookup('8.8.8.8'), 'US');
|
|
});
|
|
|
|
test('IPv6: Treffer, Grenzen, Kurzschreibweise', () => {
|
|
const g = loadGeo(fixture(CSV));
|
|
assert.equal(g.lookup('2a01:4f8::'), 'DE');
|
|
assert.equal(g.lookup('2a01:4f8:1:2:3:4:5:6'), 'DE');
|
|
assert.equal(g.lookup('2A01:04F8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF'), 'DE');
|
|
assert.equal(g.lookup('2a01:4f9::'), '');
|
|
assert.equal(g.lookup('2a01:4f7:ffff:ffff:ffff:ffff:ffff:ffff'), '');
|
|
assert.equal(g.lookup('2001:db8::1'), 'AT');
|
|
assert.equal(g.lookup('2a02:1::1'), 'CH');
|
|
assert.equal(g.lookup('2a02:1::ff'), 'CH');
|
|
assert.equal(g.lookup('2a02:1::100'), '');
|
|
assert.equal(g.lookup('2a02:1::'), '');
|
|
assert.equal(g.lookup('::1'), '');
|
|
});
|
|
|
|
test('IPv4-gemappte IPv6-Adressen zählen als IPv4', () => {
|
|
const g = loadGeo(fixture(CSV));
|
|
assert.equal(g.lookup('::ffff:5.9.1.1'), 'DE');
|
|
assert.equal(g.lookup('::FFFF:8.8.8.8'), 'US');
|
|
assert.equal(g.lookup('::ffff:808:808'), 'US');
|
|
assert.equal(g.lookup('::ffff:9.9.9.9'), '');
|
|
});
|
|
|
|
test('ZZ, ungültige Eingaben, unsortierte Datei', () => {
|
|
const g = loadGeo(fixture(CSV));
|
|
assert.equal(g.lookup('5.10.0.5'), '');
|
|
for (const bad of ['', 'abc', '1.2.3', '256.1.1.1', '1.2.3.4.5', '2001:db8::zz', ':::', '1::2::3', null, undefined, 42]) {
|
|
assert.equal(g.lookup(bad), '', String(bad));
|
|
}
|
|
const u = loadGeo(fixture('8.8.8.0,8.8.8.255,US\n1.0.0.0,1.0.0.255,AU\n2a01:4f8::,2a01:4f8::ff,DE\n2001:db8::,2001:db8::ff,AT\n'));
|
|
assert.equal(u.lookup('1.0.0.7'), 'AU');
|
|
assert.equal(u.lookup('8.8.8.8'), 'US');
|
|
assert.equal(u.lookup('2001:db8::7'), 'AT');
|
|
assert.equal(u.lookup('2a01:4f8::7'), 'DE');
|
|
});
|
|
|
|
test('fehlende Datei: alles leer, eine Warnung, kein Absturz', () => {
|
|
const warns = [];
|
|
const orig = console.warn;
|
|
console.warn = (...a) => warns.push(a.join(' '));
|
|
try {
|
|
const g = loadGeo('/nicht/vorhanden/geo.csv');
|
|
assert.equal(g.lookup('5.9.1.1'), '');
|
|
assert.equal(g.lookup('2a01:4f8::1'), '');
|
|
assert.equal(g.size, 0);
|
|
} finally { console.warn = orig; }
|
|
assert.equal(warns.length, 1);
|
|
assert.match(warns[0], /nicht lesbar/);
|
|
});
|
|
|
|
test('600k Zeilen: lädt zügig, Heap bleibt klein', () => {
|
|
const lines = [];
|
|
for (let i = 0; i < 400000; i++) lines.push(`${(i * 4096) >>> 24}.${((i * 4096) >>> 16) & 255}.${((i * 4096) >>> 8) & 255}.0,${(i * 4096) >>> 24}.${((i * 4096) >>> 16) & 255}.${((i * 4096 + 255) >>> 8) & 255}.255,${i % 7 ? 'DE' : 'AT'}`);
|
|
for (let i = 0; i < 200000; i++) lines.push(`2a00:${(i >> 8).toString(16)}:${(i & 255).toString(16)}::,2a00:${(i >> 8).toString(16)}:${(i & 255).toString(16)}:ffff:ffff:ffff:ffff:ffff,${i % 5 ? 'DE' : 'FR'}`);
|
|
const f = fixture(lines.join('\n'));
|
|
lines.length = 0;
|
|
globalThis.gc?.();
|
|
const before = process.memoryUsage().heapUsed; const rss0 = process.memoryUsage().rss;
|
|
const t0 = Date.now();
|
|
const g = loadGeo(f);
|
|
const ms = Date.now() - t0;
|
|
globalThis.gc?.();
|
|
const grow = (process.memoryUsage().heapUsed - before) / 1048576;
|
|
console.log(`# geo 600k: ${ms} ms, Heap +${grow.toFixed(1)} MB, RSS +${((process.memoryUsage().rss - rss0) / 1048576).toFixed(0)} MB, Zeilen ${g.size}`);
|
|
assert.equal(g.size, 600000);
|
|
assert.equal(g.lookup('0.0.16.5'), 'DE');
|
|
assert.equal(g.lookup('2a00:0:1::5'), 'DE');
|
|
assert.ok(grow < 100, `Heap +${grow} MB`);
|
|
});
|