mirror of
https://github.com/jason5ng32/MyIP.git
synced 2026-11-04 08:55:47 +00:00
Review findings on the ASN Profile work, mostly one class of bug: a failed upstream read as "no data", which the 7-day edge cache would then pin. - AS Rank: a 200 carrying GraphQL errors is a failure, not an unknown AS. - Radar: an answer built from partly failed segments is still shown but flagged `incomplete` and kept out of the cache, on the aggregate and on the standalone asn view. A 404 is Radar's "no such AS" and counts as empty, as does a segment that simply has no figures. - Reputation: a malformed or non-200 answer is an error. - Prefixes: a payload without `prefix_origins` is an error; [] stays valid. - Radar is `empty` when only local CAIDA counts are present. - requireValidASN enforces AS1–AS4294967295 and canonicalizes; the range rule lives once in common/asn-input.js, shared with the frontend. - The PeeringDB listing lookup goes through fetchUpstream. - New functions follow the const-arrow convention; test stubs compare parsed hostnames instead of URL substrings. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
77 lines
2.6 KiB
JavaScript
77 lines
2.6 KiB
JavaScript
// Tests for common/asn-input.js — the AS-number grammar shared by the ASN
|
|
// guards, the Whois tool (prefix required) and ASN Profile (prefix
|
|
// optional) — and its frontend/utils/asn-input.js re-export.
|
|
|
|
import assert from 'node:assert/strict';
|
|
import { describe, it } from 'node:test';
|
|
import { MAX_ASN, parseAsnInput } from '../common/asn-input.js';
|
|
import * as bridge from '../frontend/utils/asn-input.js';
|
|
|
|
describe('frontend bridge', () => {
|
|
it('re-exports the shared implementation', () => {
|
|
assert.equal(bridge.parseAsnInput, parseAsnInput);
|
|
assert.equal(bridge.MAX_ASN, MAX_ASN);
|
|
});
|
|
});
|
|
|
|
describe('parseAsnInput', () => {
|
|
it('accepts AS-prefixed and bare numbers, any case, trimmed', () => {
|
|
assert.equal(parseAsnInput('AS13335'), 13335);
|
|
assert.equal(parseAsnInput('as13335'), 13335);
|
|
assert.equal(parseAsnInput('As13335'), 13335);
|
|
assert.equal(parseAsnInput('13335'), 13335);
|
|
assert.equal(parseAsnInput(' AS64500 '), 64500);
|
|
assert.equal(parseAsnInput(13335), 13335);
|
|
});
|
|
|
|
it('normalizes leading zeros', () => {
|
|
assert.equal(parseAsnInput('AS013335'), 13335);
|
|
});
|
|
|
|
it('honours the 32-bit range and rejects AS0', () => {
|
|
assert.equal(parseAsnInput(String(MAX_ASN)), 4294967295);
|
|
assert.equal(parseAsnInput('AS4294967296'), null);
|
|
assert.equal(parseAsnInput('AS0'), null);
|
|
assert.equal(parseAsnInput('0'), null);
|
|
});
|
|
|
|
it('rejects more than ten digits even when the value fits', () => {
|
|
assert.equal(parseAsnInput('00000013335'), null);
|
|
});
|
|
|
|
it('rejects anything else', () => {
|
|
for (const raw of ['', 'AS', 'AS 13335', 'ASN13335', '13335a', '-1', '1.5', 'AS13335/24', null, undefined, {}]) {
|
|
assert.equal(parseAsnInput(raw), null, String(raw));
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('parseAsnInput — requirePrefix', () => {
|
|
const strict = (raw) => parseAsnInput(raw, { requirePrefix: true });
|
|
|
|
it('accepts the AS prefix in any case', () => {
|
|
assert.equal(strict('AS13335'), 13335);
|
|
assert.equal(strict('as13335'), 13335);
|
|
assert.equal(strict('As13335'), 13335);
|
|
assert.equal(strict(' aS64500 '), 64500);
|
|
});
|
|
|
|
it('rejects a bare number', () => {
|
|
assert.equal(strict('13335'), null);
|
|
assert.equal(strict(13335), null);
|
|
});
|
|
|
|
it('keeps the same range rules', () => {
|
|
assert.equal(strict('AS4294967295'), MAX_ASN);
|
|
assert.equal(strict('AS4294967296'), null);
|
|
assert.equal(strict('AS0'), null);
|
|
assert.equal(strict('AS00000013335'), null);
|
|
});
|
|
|
|
it('does not take IPs or domains', () => {
|
|
for (const raw of ['1.1.1.1', '2606:4700::1111', 'example.com', 'as13335.net']) {
|
|
assert.equal(strict(raw), null, raw);
|
|
}
|
|
});
|
|
});
|