fix(client,testing,build): improve TypeScript compatibility for DNS client parsing and test suite

This commit is contained in:
2026-04-30 12:48:49 +00:00
parent 510801b109
commit 199dfe7ba3
18 changed files with 1944 additions and 3435 deletions
+12 -10
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8500;
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
try {
await server.stop();
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
}
}
@@ -126,8 +128,8 @@ tap.test('DNSSEC should sign entire RRset together, not individual records', asy
const dnsResponse = await responsePromise;
// Count NS and RRSIG records
const nsAnswers = dnsResponse.answers.filter(a => a.type === 'NS');
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
const nsAnswers = dnsResponse.answers!.filter(a => a.type === 'NS');
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
console.log('NS records returned:', nsAnswers.length);
console.log('RRSIG records returned:', rrsigAnswers.length);
@@ -197,7 +199,7 @@ tap.test('SOA records should be properly serialized and returned', async () => {
const dnsResponse = await responsePromise;
// Should have SOA record in response
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
const soaData = (soaAnswers[0] as any).data;
@@ -269,7 +271,7 @@ tap.test('Primary nameserver should be configurable', async () => {
const dnsResponse = await responsePromise;
// Should have SOA record with custom nameserver
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
const soaData = (soaAnswers[0] as any).data;
@@ -356,8 +358,8 @@ tap.test('Multiple A records should have single RRSIG when DNSSEC is enabled', a
const dnsResponse = await responsePromise;
const aAnswers = dnsResponse.answers.filter(a => a.type === 'A');
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
const aAnswers = dnsResponse.answers!.filter(a => a.type === 'A');
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
console.log('A records:', aAnswers.length);
console.log('RRSIG records:', rrsigAnswers.length);
@@ -370,4 +372,4 @@ tap.test('Multiple A records should have single RRSIG when DNSSEC is enabled', a
dnsServer = null;
});
export default tap.start();
export default tap.start();
+9 -7
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8600;
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
try {
await server.stop();
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
}
}
@@ -85,7 +87,7 @@ tap.test('SOA records should be returned for non-existent domains', async () =>
const dnsResponse = await responsePromise;
console.log('✅ SOA response received');
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
const soaData = (soaAnswers[0] as any).data;
@@ -151,7 +153,7 @@ tap.test('Primary nameserver should be configurable', async () => {
const dnsResponse = await responsePromise;
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
const soaData = (soaAnswers[0] as any).data;
@@ -215,7 +217,7 @@ tap.test('Default primary nameserver with FQDN', async () => {
const dnsResponse = await responsePromise;
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
const soaData = (soaAnswers[0] as any).data;
console.log('✅ FQDN primary nameserver:', soaData.mname);
@@ -225,4 +227,4 @@ tap.test('Default primary nameserver with FQDN', async () => {
dnsServer = null;
});
export default tap.start();
export default tap.start();
+23 -21
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8300;
@@ -34,7 +36,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
await Promise.race([stopPromise, timeoutPromise]);
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
// Force close if normal stop fails
try {
@@ -49,7 +51,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
(server as any).udpServer = null;
}
} catch (forceError) {
console.log('Force cleanup error:', forceError.message || forceError);
console.log('Force cleanup error:', forceError instanceof Error ? forceError.message : forceError);
}
}
}
@@ -128,13 +130,13 @@ tap.test('should now return multiple NS records after fix', async () => {
const dnsResponse = await responsePromise;
console.log('Fixed behavior - NS records returned:', dnsResponse.answers.length);
console.log('NS records:', dnsResponse.answers.filter(a => a.type === 'NS').map(a => a.data));
console.log('Fixed behavior - NS records returned:', dnsResponse.answers!.length);
console.log('NS records:', dnsResponse.answers!.filter(a => a.type === 'NS').map(a => (a as any).data));
// FIXED BEHAVIOR: Should now return both NS records
const nsAnswers = dnsResponse.answers.filter(a => a.type === 'NS');
const nsAnswers = dnsResponse.answers!.filter(a => a.type === 'NS');
expect(nsAnswers.length).toEqual(2);
expect(nsAnswers.map(a => a.data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
expect(nsAnswers.map(a => (a as any).data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
await stopServer(dnsServer);
dnsServer = null;
@@ -206,13 +208,13 @@ tap.test('should support round-robin DNS with multiple A records', async () => {
const dnsResponse = await responsePromise;
console.log('Fixed behavior - A records returned:', dnsResponse.answers.length);
console.log('A records:', dnsResponse.answers.filter(a => a.type === 'A').map(a => a.data));
console.log('Fixed behavior - A records returned:', dnsResponse.answers!.length);
console.log('A records:', dnsResponse.answers!.filter(a => a.type === 'A').map(a => (a as any).data));
// FIXED BEHAVIOR: Should return all A records for round-robin
const aAnswers = dnsResponse.answers.filter(a => a.type === 'A');
const aAnswers = dnsResponse.answers!.filter(a => a.type === 'A');
expect(aAnswers.length).toEqual(3);
expect(aAnswers.map(a => a.data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
expect(aAnswers.map(a => (a as any).data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
await stopServer(dnsServer);
dnsServer = null;
@@ -289,8 +291,8 @@ tap.test('should return multiple TXT records', async () => {
const dnsResponse = await responsePromise;
console.log('Fixed behavior - TXT records returned:', dnsResponse.answers.length);
const txtAnswers = dnsResponse.answers.filter(a => a.type === 'TXT');
console.log('Fixed behavior - TXT records returned:', dnsResponse.answers!.length);
const txtAnswers = dnsResponse.answers!.filter(a => a.type === 'TXT');
console.log('TXT records count:', txtAnswers.length);
// FIXED BEHAVIOR: Should return all TXT records
@@ -388,10 +390,10 @@ tap.test('should handle DNSSEC correctly with multiple records', async () => {
const dnsResponse = await responsePromise;
console.log('DNSSEC response - total answers:', dnsResponse.answers.length);
console.log('DNSSEC response - total answers:', dnsResponse.answers!.length);
const nsAnswers = dnsResponse.answers.filter(a => a.type === 'NS');
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
const nsAnswers = dnsResponse.answers!.filter(a => a.type === 'NS');
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
console.log('NS records:', nsAnswers.length);
console.log('RRSIG records:', rrsigAnswers.length);
@@ -417,7 +419,7 @@ tap.test('should not return duplicate records when same handler registered multi
});
// Register the same handler multiple times (edge case)
const sameHandler = (question) => {
const sameHandler = (question: smartdns.IDnsQuestion) => {
return {
name: question.name,
type: 'A',
@@ -470,16 +472,16 @@ tap.test('should not return duplicate records when same handler registered multi
const dnsResponse = await responsePromise;
const aAnswers = dnsResponse.answers.filter(a => a.type === 'A');
const aAnswers = dnsResponse.answers!.filter(a => a.type === 'A');
console.log('Duplicate handler test - A records returned:', aAnswers.length);
// Even though handler is registered 3 times, we get 3 identical records
// This is expected behavior - the DNS server doesn't deduplicate
expect(aAnswers.length).toEqual(3);
expect(aAnswers.every(a => a.data === '10.0.0.1')).toEqual(true);
expect(aAnswers.every(a => (a as any).data === '10.0.0.1')).toEqual(true);
await stopServer(dnsServer);
dnsServer = null;
});
export default tap.start();
export default tap.start();
+17 -15
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8400;
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
try {
await server.stop();
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
}
}
@@ -105,12 +107,12 @@ tap.test('Multiple NS records should work correctly', async () => {
const dnsResponse = await responsePromise;
console.log('✅ NS records returned:', dnsResponse.answers.length);
console.log('✅ NS records:', dnsResponse.answers.map(a => (a as any).data));
console.log('✅ NS records returned:', dnsResponse.answers!.length);
console.log('✅ NS records:', dnsResponse.answers!.map(a => (a as any).data));
// SUCCESS: Multiple NS records are now returned
expect(dnsResponse.answers.length).toEqual(2);
expect(dnsResponse.answers.map(a => (a as any).data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
expect(dnsResponse.answers!.length).toEqual(2);
expect(dnsResponse.answers!.map(a => (a as any).data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
await stopServer(dnsServer);
dnsServer = null;
@@ -181,12 +183,12 @@ tap.test('Multiple A records for round-robin DNS', async () => {
const dnsResponse = await responsePromise;
console.log('✅ A records returned:', dnsResponse.answers.length);
console.log('✅ A records:', dnsResponse.answers.map(a => (a as any).data));
console.log('✅ A records returned:', dnsResponse.answers!.length);
console.log('✅ A records:', dnsResponse.answers!.map(a => (a as any).data));
// SUCCESS: All A records for round-robin DNS
expect(dnsResponse.answers.length).toEqual(3);
expect(dnsResponse.answers.map(a => (a as any).data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
expect(dnsResponse.answers!.length).toEqual(3);
expect(dnsResponse.answers!.map(a => (a as any).data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
await stopServer(dnsServer);
dnsServer = null;
@@ -262,12 +264,12 @@ tap.test('Multiple TXT records', async () => {
const dnsResponse = await responsePromise;
console.log('✅ TXT records returned:', dnsResponse.answers.length);
console.log('✅ TXT records returned:', dnsResponse.answers!.length);
// SUCCESS: All TXT records are returned
expect(dnsResponse.answers.length).toEqual(3);
expect(dnsResponse.answers!.length).toEqual(3);
const txtData = dnsResponse.answers.map(a => (a as any).data[0].toString());
const txtData = dnsResponse.answers!.map(a => (a as any).data[0].toString());
expect(txtData.some(d => d.includes('spf1'))).toEqual(true);
expect(txtData.some(d => d.includes('DKIM1'))).toEqual(true);
expect(txtData.some(d => d.includes('google-site-verification'))).toEqual(true);
@@ -276,4 +278,4 @@ tap.test('Multiple TXT records', async () => {
dnsServer = null;
});
export default tap.start();
export default tap.start();
+25 -23
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8200;
@@ -34,7 +36,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
await Promise.race([stopPromise, timeoutPromise]);
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
// Force close if normal stop fails
try {
@@ -49,7 +51,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
(server as any).udpServer = null;
}
} catch (forceError) {
console.log('Force cleanup error:', forceError.message || forceError);
console.log('Force cleanup error:', forceError instanceof Error ? forceError.message : forceError);
}
}
}
@@ -128,12 +130,12 @@ tap.test('should properly return multiple NS records', async () => {
const dnsResponse = await responsePromise;
console.log('Current behavior - NS records returned:', dnsResponse.answers.length);
console.log('NS records:', dnsResponse.answers.map(a => (a as any).data));
console.log('Current behavior - NS records returned:', dnsResponse.answers!.length);
console.log('NS records:', dnsResponse.answers!.map(a => (a as any).data));
// Should return all registered NS records
expect(dnsResponse.answers.length).toEqual(2);
const nsData = dnsResponse.answers.map(a => (a as any).data).sort();
expect(dnsResponse.answers!.length).toEqual(2);
const nsData = dnsResponse.answers!.map(a => (a as any).data).sort();
expect(nsData).toEqual(['ns1.example.com', 'ns2.example.com']);
await stopServer(dnsServer);
@@ -225,12 +227,12 @@ tap.test('should properly return multiple A records for round-robin DNS', async
const dnsResponse = await responsePromise;
console.log('Current behavior - A records returned:', dnsResponse.answers.length);
console.log('A records:', dnsResponse.answers.map(a => (a as any).data));
console.log('Current behavior - A records returned:', dnsResponse.answers!.length);
console.log('A records:', dnsResponse.answers!.map(a => (a as any).data));
// Should return all registered A records for round-robin DNS
expect(dnsResponse.answers.length).toEqual(3);
const aData = dnsResponse.answers.map(a => (a as any).data).sort();
expect(dnsResponse.answers!.length).toEqual(3);
const aData = dnsResponse.answers!.map(a => (a as any).data).sort();
expect(aData).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
await stopServer(dnsServer);
@@ -322,12 +324,12 @@ tap.test('should properly return multiple TXT records', async () => {
const dnsResponse = await responsePromise;
console.log('Current behavior - TXT records returned:', dnsResponse.answers.length);
console.log('TXT records:', dnsResponse.answers.map(a => (a as any).data));
console.log('Current behavior - TXT records returned:', dnsResponse.answers!.length);
console.log('TXT records:', dnsResponse.answers!.map(a => (a as any).data));
// Should return all registered TXT records
expect(dnsResponse.answers.length).toEqual(3);
const txtData = dnsResponse.answers.map(a => (a as any).data[0]).sort();
expect(dnsResponse.answers!.length).toEqual(3);
const txtData = dnsResponse.answers!.map(a => (a as any).data[0]).sort();
expect(txtData[0]).toInclude('google-site-verification');
expect(txtData[1]).toInclude('DKIM1');
expect(txtData[2]).toInclude('spf1');
@@ -408,17 +410,17 @@ tap.test('should rotate between records when using a single handler', async () =
const [response1, response2] = await Promise.all([responsePromise1, responsePromise2]);
console.log('First query NS:', (response1.answers[0] as any).data);
console.log('Second query NS:', (response2.answers[0] as any).data);
console.log('First query NS:', (response1.answers![0] as any).data);
console.log('Second query NS:', (response2.answers![0] as any).data);
// This pattern rotates between records but returns one at a time per query
expect(response1.answers.length).toEqual(1);
expect(response2.answers.length).toEqual(1);
expect((response1.answers[0] as any).data).toEqual('ns1.example.com');
expect((response2.answers[0] as any).data).toEqual('ns2.example.com');
expect(response1.answers!.length).toEqual(1);
expect(response2.answers!.length).toEqual(1);
expect((response1.answers![0] as any).data).toEqual('ns1.example.com');
expect((response2.answers![0] as any).data).toEqual('ns2.example.com');
await stopServer(dnsServer);
dnsServer = null;
});
export default tap.start();
export default tap.start();
+27 -19
View File
@@ -1,6 +1,6 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { execSync } from 'child_process';
import * as dnsPacket from 'dns-packet';
@@ -12,6 +12,8 @@ import * as os from 'os';
import * as smartdns from '../ts_server/index.js';
const tapNodeTools = new TapNodeTools(tap);
// Generate a real self-signed certificate using OpenSSL
function generateSelfSignedCert() {
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cert-'));
@@ -48,7 +50,7 @@ function generateSelfSignedCert() {
}
// Cache the generated certificate for performance
let cachedCert = null;
let cachedCert: { key: string; cert: string } | null = null;
// Helper function to get certificate
function getTestCertificate() {
@@ -108,7 +110,7 @@ const acmeClientMock = {
},
forge: {
createCsr({commonName, altNames}) {
createCsr({ commonName, altNames }: { commonName: string; altNames: string[] }) {
return Promise.resolve({
csr: Buffer.from('mock-csr-data')
});
@@ -125,7 +127,7 @@ const acmeClientMock = {
// Override generateKeyPairSync to use our test key for certificate generation in tests
const originalGenerateKeyPairSync = plugins.crypto.generateKeyPairSync;
plugins.crypto.generateKeyPairSync = function(type, options) {
(plugins.crypto.generateKeyPairSync as any) = function(this: any, type: string, options?: any) {
if (type === 'rsa' &&
options?.modulusLength === 2048 &&
options?.privateKeyEncoding?.type === 'pkcs8') {
@@ -143,10 +145,10 @@ plugins.crypto.generateKeyPairSync = function(type, options) {
}
// Use the original function for other cases
return originalGenerateKeyPairSync.apply(this, arguments);
return (originalGenerateKeyPairSync as any).apply(this, arguments);
};
let dnsServer: smartdns.DnsServer;
let dnsServer: smartdns.DnsServer | null;
const testCertDir = path.join(process.cwd(), 'test-certs');
// Helper to clean up test certificate directory
@@ -187,7 +189,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
await Promise.race([stopPromise, timeoutPromise]);
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
// Force close if normal stop fails
try {
@@ -202,7 +204,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
(server as any).udpServer = null;
}
} catch (forceError) {
console.log('Force cleanup error:', forceError.message || forceError);
console.log('Force cleanup error:', forceError instanceof Error ? forceError.message : forceError);
}
}
}
@@ -400,7 +402,7 @@ tap.test('lets query over https', async () => {
const response = await fetch(`https://localhost:${httpsPort}/dns-query`, {
method: 'POST',
body: query,
body: query as unknown as BodyInit,
headers: {
'Content-Type': 'application/dns-message',
}
@@ -411,9 +413,9 @@ tap.test('lets query over https', async () => {
const responseData = await response.arrayBuffer();
const dnsResponse = dnsPacket.decode(Buffer.from(responseData));
console.log(dnsResponse.answers[0]);
console.log(dnsResponse.answers![0]);
expect(dnsResponse.answers[0]).toEqual({
expect(dnsResponse.answers![0]).toEqual({
name: 'dnsly_a.bleu.de',
type: 'A',
class: 'IN',
@@ -494,9 +496,9 @@ tap.test('lets query over udp', async () => {
const dnsResponse = await responsePromise;
console.log(dnsResponse.answers[0]);
console.log(dnsResponse.answers![0]);
expect(dnsResponse.answers[0]).toEqual({
expect(dnsResponse.answers![0]).toEqual({
name: 'dnsly_a.bleu.de',
type: 'A',
class: 'IN',
@@ -674,14 +676,17 @@ tap.test('should reject invalid IP addresses', async () => {
udpBindInterface: 'invalid-ip',
});
let error1 = null;
let error1: Error | null = null;
try {
await dnsServer.start();
} catch (err) {
error1 = err;
error1 = err instanceof Error ? err : new Error(String(err));
}
expect(error1).toBeDefined();
if (!error1) {
throw new Error('Expected invalid UDP bind interface to throw');
}
expect(error1.message).toContain('Invalid UDP bind interface');
// Test invalid HTTPS interface
@@ -694,14 +699,17 @@ tap.test('should reject invalid IP addresses', async () => {
httpsBindInterface: '999.999.999.999',
});
let error2 = null;
let error2: Error | null = null;
try {
await dnsServer.start();
} catch (err) {
error2 = err;
error2 = err instanceof Error ? err : new Error(String(err));
}
expect(error2).toBeDefined();
if (!error2) {
throw new Error('Expected invalid HTTPS bind interface to throw');
}
expect(error2.message).toContain('Invalid HTTPS bind interface');
dnsServer = null;
@@ -740,7 +748,7 @@ tap.test('should work with IPv6 localhost if available', async () => {
await stopServer(dnsServer);
} catch (err) {
console.log('IPv6 binding failed:', err.message);
console.log('IPv6 binding failed:', err instanceof Error ? err.message : err);
await stopServer(dnsServer);
throw err;
}
@@ -771,4 +779,4 @@ tap.test('should stop the server', async () => {
dnsServer = null;
});
export default tap.start();
export default tap.start();
+15 -13
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8700;
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
try {
await server.stop();
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
}
}
@@ -96,7 +98,7 @@ tap.test('Direct SOA query should work without timeout', async () => {
const dnsResponse = dnsPacket.decode(msg);
resolve(dnsResponse);
} catch (e) {
reject(new Error(`Failed to decode response: ${e.message}`));
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
}
client.close();
});
@@ -118,9 +120,9 @@ tap.test('Direct SOA query should work without timeout', async () => {
try {
const dnsResponse = await responsePromise;
console.log('SOA response received:', dnsResponse.answers.length, 'answers');
console.log('SOA response received:', dnsResponse.answers!.length, 'answers');
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
const soaData = (soaAnswers[0] as any).data;
@@ -189,7 +191,7 @@ tap.test('SOA query with DNSSEC should work', async () => {
const dnsResponse = dnsPacket.decode(msg);
resolve(dnsResponse);
} catch (e) {
reject(new Error(`Failed to decode response: ${e.message}`));
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
}
client.close();
});
@@ -211,10 +213,10 @@ tap.test('SOA query with DNSSEC should work', async () => {
try {
const dnsResponse = await responsePromise;
console.log('Response received with', dnsResponse.answers.length, 'answers');
console.log('Response received with', dnsResponse.answers!.length, 'answers');
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
console.log('SOA records found:', soaAnswers.length);
console.log('RRSIG records found:', rrsigAnswers.length);
@@ -312,7 +314,7 @@ tap.test('SOA serialization produces correct wire format', async () => {
const dnsResponse = dnsPacket.decode(msg);
resolve(dnsResponse);
} catch (e) {
reject(new Error(`Failed to decode response: ${e.message}`));
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
}
client.close();
});
@@ -334,7 +336,7 @@ tap.test('SOA serialization produces correct wire format', async () => {
try {
const dnsResponse = await responsePromise;
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
const soaData = (soaAnswers[0] as any).data;
@@ -358,4 +360,4 @@ tap.test('SOA serialization produces correct wire format', async () => {
dnsServer = null;
});
export default tap.start();
export default tap.start();
+17 -15
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8900;
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
try {
await server.stop();
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
}
}
@@ -118,9 +120,9 @@ tap.test('SOA records work for all scenarios', async () => {
client.send(soaQuery, udpPort, 'localhost');
});
console.log('Direct SOA query response:', response.answers.length, 'answers');
expect(response.answers.length).toEqual(1);
expect(response.answers[0].type).toEqual('SOA');
console.log('Direct SOA query response:', response.answers!.length, 'answers');
expect(response.answers!.length).toEqual(1);
expect(response.answers![0].type).toEqual('SOA');
// Test 2: Non-existent domain query (should get SOA in authority)
console.log('\n--- Test 2: Non-existent domain query ---');
@@ -153,8 +155,8 @@ tap.test('SOA records work for all scenarios', async () => {
client.send(nxQuery, udpPort, 'localhost');
});
console.log('Non-existent query response:', response.answers.length, 'answers');
const soaAnswers = response.answers.filter(a => a.type === 'SOA');
console.log('Non-existent query response:', response.answers!.length, 'answers');
const soaAnswers = response.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
// Test 3: SOA with DNSSEC
@@ -197,11 +199,11 @@ tap.test('SOA records work for all scenarios', async () => {
client.send(dnssecQuery, udpPort, 'localhost');
});
console.log('DNSSEC SOA query response:', response.answers.length, 'answers');
console.log('Answer types:', response.answers.map(a => a.type));
expect(response.answers.length).toEqual(2); // SOA + RRSIG
expect(response.answers.some(a => a.type === 'SOA')).toEqual(true);
expect(response.answers.some(a => a.type === 'RRSIG')).toEqual(true);
console.log('DNSSEC SOA query response:', response.answers!.length, 'answers');
console.log('Answer types:', response.answers!.map(a => a.type));
expect(response.answers!.length).toEqual(2); // SOA + RRSIG
expect(response.answers!.some(a => a.type === 'SOA')).toEqual(true);
expect(response.answers!.some(a => a.type === 'RRSIG')).toEqual(true);
client.close();
await stopServer(dnsServer);
@@ -259,7 +261,7 @@ tap.test('Configurable primary nameserver works correctly', async () => {
client.send(query, udpPort, 'localhost');
});
const soaAnswers = response.answers.filter(a => a.type === 'SOA');
const soaAnswers = response.answers!.filter(a => a.type === 'SOA');
console.log('✅ Configured primary nameserver:', (soaAnswers[0] as any).data.mname);
expect((soaAnswers[0] as any).data.mname).toEqual('master.test.com');
@@ -268,4 +270,4 @@ tap.test('Configurable primary nameserver works correctly', async () => {
dnsServer = null;
});
export default tap.start();
export default tap.start();
+8 -6
View File
@@ -1,12 +1,14 @@
import * as plugins from '../ts_server/plugins.js';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Port management for tests
let nextHttpsPort = 8800;
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
try {
await server.stop();
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
}
}
@@ -98,7 +100,7 @@ tap.test('Simple SOA query without DNSSEC', async () => {
const dnsResponse = await responsePromise;
console.log('✅ SOA response without DNSSEC received');
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
const soaData = (soaAnswers[0] as any).data;
@@ -191,11 +193,11 @@ tap.test('Direct SOA query without DNSSEC', async () => {
const dnsResponse = await responsePromise;
console.log('✅ Direct SOA query succeeded');
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
expect(soaAnswers.length).toEqual(1);
await stopServer(dnsServer);
dnsServer = null;
});
export default tap.start();
export default tap.start();
+14 -12
View File
@@ -1,11 +1,13 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
import * as dnsPacket from 'dns-packet';
import * as dgram from 'dgram';
import * as smartdns from '../ts_server/index.js';
let dnsServer: smartdns.DnsServer;
const tapNodeTools = new TapNodeTools(tap);
let dnsServer: smartdns.DnsServer | null;
// Cleanup function for servers
async function stopServer(server: smartdns.DnsServer | null | undefined) {
@@ -16,7 +18,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
try {
await server.stop();
} catch (e) {
console.log('Handled error when stopping server:', e.message || e);
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
}
}
@@ -78,7 +80,7 @@ tap.test('Test SOA with DNSSEC timing', async () => {
const dnsResponse = dnsPacket.decode(msg);
resolve(dnsResponse);
} catch (e) {
reject(new Error(`Failed to decode response: ${e.message}`));
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
}
client.close();
});
@@ -103,11 +105,11 @@ tap.test('Test SOA with DNSSEC timing', async () => {
try {
const dnsResponse = await responsePromise;
console.log('Response details:');
console.log('- Answers:', dnsResponse.answers.length);
console.log('- Answer types:', dnsResponse.answers.map(a => a.type));
console.log('- Answers:', dnsResponse.answers!.length);
console.log('- Answer types:', dnsResponse.answers!.map(a => a.type));
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
console.log('- SOA records:', soaAnswers.length);
console.log('- RRSIG records:', rrsigAnswers.length);
@@ -187,7 +189,7 @@ tap.test('DNSSEC signing completes within reasonable time', async () => {
const dnsResponse = dnsPacket.decode(msg);
resolve(dnsResponse);
} catch (e) {
reject(new Error(`Failed to decode response: ${e.message}`));
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
}
client.close();
});
@@ -215,8 +217,8 @@ tap.test('DNSSEC signing completes within reasonable time', async () => {
expect(elapsed).toBeLessThan(2000);
// Verify correctness: SOA + RRSIG present
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
expect(soaAnswers.length).toEqual(1);
expect(rrsigAnswers.length).toBeGreaterThan(0);
@@ -234,4 +236,4 @@ tap.test('DNSSEC signing completes within reasonable time', async () => {
dnsServer = null;
});
export default tap.start();
export default tap.start();