Files
AriWeb-Suite/modules/webmaker/test/dnszone-import.test.js
T

35 lines
4.7 KiB
JavaScript

'use strict';
// v1.6.33 (요구 1) 이전된 영역 받기 — 공용 DNS 상태별 결과: 미등록/위임 없음(실패·원인), 네임서버 응답 없음(실패·원인), 레코드 없음("zone 파일 구성을 찾을 수 없습니다"+빈 영역), 레코드 있음(가져옴). 모의 리졸버·모의 공급자, 네트워크 없음.
const test = require('node:test'); const assert = require('node:assert/strict');
const fs = require('fs'); const path = require('path'); const os = require('os');
const ROOT = path.join(__dirname, '..');
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'wm-dz-')); process.env.DATA_ROOT = tmp; process.env.DATA_DIR = path.join(tmp, 'sites');
const dz = require(ROOT + '/lib/dnszone');
// 모의 공급자: 영역 생성·레코드 추가만 기록
const made = []; dz.PROVIDERS.mock = { id: 'mock', ready: () => true, createZone: async (z) => { made.push({ zone: z }); return { id: 'z1', name: z, nameServers: ['ns1.mock', 'ns2.mock'] }; }, updateRecords: async (z, { add }) => { made.push({ zone: z, add }); return { ok: true }; }, listZones: async () => [], getZone: async () => null, deleteZone: async () => ({}), listRecords: async () => [], nameServers: async () => ['ns1.mock'] };
dz.LABELS.mock = 'Mock';
const err = (code) => Object.assign(new Error(code), { code });
const resolverFor = (m) => ({ resolveNs: async (z) => { if (m.ns instanceof Error) throw m.ns; return m.ns; }, resolveSoa: async () => { if (m.soa instanceof Error) throw m.soa; return m.soa || {}; }, resolve4: async (n) => m.a && m.a[n] ? m.a[n] : (() => { throw err('ENODATA'); })(), resolve6: async () => { throw err('ENODATA'); }, resolveCname: async () => { throw err('ENODATA'); }, resolveTxt: async (n) => m.txt && m.txt[n] ? m.txt[n] : (() => { throw err('ENODATA'); })(), resolveMx: async (n) => m.mx && m.mx[n] ? m.mx[n] : (() => { throw err('ENODATA'); })() });
test('미등록·위임 없음(NXDOMAIN) → 실패, 원인 설명', async () => {
await assert.rejects(dz.importZone('nope.example', 'admin', 'mock', { resolver: resolverFor({ ns: err('ENOTFOUND') }) }), (e) => e.status === 409 && /등록되어 있지 않거나|네임서버\(NS\)가 지정되지/.test(e.message) && /존재하지 않습니다/.test(e.message));
assert.equal(made.length, 0, '영역을 만들지 않음');
const a = dz.auditList(5).find((x) => x.action === 'zone.import'); assert.ok(a && a.ok === false && /NXDOMAIN/.test(a.reason), '실패도 감사 기록');
});
test('네임서버가 응답하지 않음(SERVFAIL/TIMEOUT) → 실패, 원인 설명', async () => {
await assert.rejects(dz.importZone('dead.example', 'admin', 'mock', { resolver: resolverFor({ ns: err('ESERVFAIL') }) }), /SERVFAIL|응답을 주지 못했/);
await assert.rejects(dz.importZone('down.example', 'admin', 'mock', { resolver: resolverFor({ ns: err('ETIMEOUT') }) }), /연결할 수 없습니다/);
assert.equal(made.length, 0);
});
test('위임은 되어 있지만 레코드가 없음 → 실패가 아니라 "zone 파일 구성을 찾을 수 없습니다" + 빈 영역', async () => {
const r = await dz.importZone('empty.example', 'admin', 'mock', { resolver: resolverFor({ ns: ['ns1.other.net.', 'ns2.other.net'] }) });
assert.equal(r.empty, true); assert.equal(r.imported, 0); assert.match(r.message, /zone 파일 구성을 찾을 수 없습니다/); assert.deepEqual(r.currentNs, ['ns1.other.net', 'ns2.other.net']); assert.deepEqual(r.nameServers, ['ns1.mock', 'ns2.mock']);
assert.equal(made.filter((m) => m.zone === 'empty.example').length, 1, '빈 영역은 만들고 레코드 추가는 없음');
});
test('레코드가 있으면 가져온다 (A·MX·TXT)', async () => {
const r = await dz.importZone('live.example', 'admin', 'mock', { resolver: resolverFor({ ns: ['ns1.x'], a: { 'live.example': ['203.0.113.5'], 'www.live.example': ['203.0.113.5'] }, mx: { 'live.example': [{ exchange: 'mail.live.example', priority: 10 }] }, txt: { 'live.example': [['v=spf1 -all']] } }) });
assert.equal(r.empty, false); assert.equal(r.imported, 4); assert.match(r.message, /레코드 4개/);
const add = made.find((m) => m.zone === 'live.example' && m.add).add; assert.ok(add.some((x) => x.type === 'MX' && x.prio === 10)); assert.ok(add.some((x) => x.type === 'TXT' && x.value === 'v=spf1 -all'));
});
test('공급자 접속 정보가 없으면 DNS 를 읽기 전에 503', async () => { await assert.rejects(dz.importZone('x.example', 'admin', 'route53', { resolver: resolverFor({ ns: ['ns'] }) }), (e) => e.status === 503); });
test('오류 코드 설명표', () => { assert.match(dz.describeDnsError('ENOTFOUND', 'a.b'), /NXDOMAIN/); assert.equal(dz.describeDnsError('ENODATA', 'a.b'), ''); assert.match(dz.describeDnsError('EWEIRD', 'a.b'), /EWEIRD/); });