229 lines
7.1 KiB
TypeScript
229 lines
7.1 KiB
TypeScript
/**
|
|
* Unit tests for DNSBL functions
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import {
|
|
reverseIPv4,
|
|
isIPv4,
|
|
getCacheEntry,
|
|
setCacheEntry,
|
|
getCacheSize,
|
|
matchesDNSBL,
|
|
parseQuery,
|
|
} from '../src/dnsbl.js';
|
|
import type { DNSBLConfig } from '../src/types.js';
|
|
|
|
describe('DNSBL Functions', () => {
|
|
describe('reverseIPv4', () => {
|
|
it('should reverse a valid IPv4 address', () => {
|
|
expect(reverseIPv4('192.168.1.10')).toBe('10.1.168.192');
|
|
});
|
|
|
|
it('should handle 127.0.0.1', () => {
|
|
expect(reverseIPv4('127.0.0.1')).toBe('1.0.0.127');
|
|
});
|
|
|
|
it('should handle 0.0.0.0', () => {
|
|
expect(reverseIPv4('0.0.0.0')).toBe('0.0.0.0');
|
|
});
|
|
|
|
it('should handle 255.255.255.255', () => {
|
|
expect(reverseIPv4('255.255.255.255')).toBe('255.255.255.255');
|
|
});
|
|
|
|
it('should return null for invalid IPv4', () => {
|
|
expect(reverseIPv4('not-an-ip')).toBeNull();
|
|
});
|
|
|
|
it('should return null for IPv6 addresses', () => {
|
|
expect(reverseIPv4('::1')).toBeNull();
|
|
expect(reverseIPv4('2001:db8::1')).toBeNull();
|
|
});
|
|
|
|
it('should return null for partial IPs', () => {
|
|
expect(reverseIPv4('192.168.1')).toBeNull();
|
|
expect(reverseIPv4('192.168')).toBeNull();
|
|
});
|
|
|
|
it('should return null for IPs with invalid octets', () => {
|
|
expect(reverseIPv4('192.168.1.256')).toBeNull();
|
|
expect(reverseIPv4('192.168.1.1000')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('isIPv4', () => {
|
|
it('should return true for valid IPv4 addresses', () => {
|
|
expect(isIPv4('192.168.1.1')).toBe(true);
|
|
expect(isIPv4('127.0.0.1')).toBe(true);
|
|
expect(isIPv4('0.0.0.0')).toBe(true);
|
|
expect(isIPv4('255.255.255.255')).toBe(true);
|
|
});
|
|
|
|
it('should return false for IPv6 addresses', () => {
|
|
expect(isIPv4('::1')).toBe(false);
|
|
expect(isIPv4('2001:db8::1')).toBe(false);
|
|
});
|
|
|
|
it('should return false for invalid strings', () => {
|
|
expect(isIPv4('not-an-ip')).toBe(false);
|
|
expect(isIPv4('')).toBe(false);
|
|
expect(isIPv4('192.168.1')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('Cache functions', () => {
|
|
beforeEach(() => {
|
|
// Clear cache by setting entries and letting them expire
|
|
// Note: In a real implementation, we'd want a clearCache() function
|
|
});
|
|
|
|
it('should store and retrieve cache entries', () => {
|
|
const query = 'test-cache-1.dnsbl.example.com';
|
|
setCacheEntry(query, ['127.0.0.2']);
|
|
|
|
const entry = getCacheEntry(query, 3600);
|
|
expect(entry).not.toBeNull();
|
|
expect(entry?.result).toEqual(['127.0.0.2']);
|
|
});
|
|
|
|
it('should return null for non-existent entries', () => {
|
|
const entry = getCacheEntry('nonexistent.query.com', 3600);
|
|
expect(entry).toBeNull();
|
|
});
|
|
|
|
it('should expire old entries', () => {
|
|
const query = 'test-cache-expire.dnsbl.example.com';
|
|
setCacheEntry(query, ['127.0.0.2']);
|
|
|
|
// With cacheTime of 0, entry should be expired
|
|
const entry = getCacheEntry(query, 0);
|
|
expect(entry).toBeNull();
|
|
});
|
|
|
|
it('should track cache size', () => {
|
|
const initialSize = getCacheSize();
|
|
const query = `test-cache-size-${Date.now()}.dnsbl.example.com`;
|
|
setCacheEntry(query, ['127.0.0.2']);
|
|
|
|
expect(getCacheSize()).toBeGreaterThanOrEqual(initialSize);
|
|
});
|
|
|
|
it('should handle null results (pending lookups)', () => {
|
|
const query = 'test-cache-null.dnsbl.example.com';
|
|
setCacheEntry(query, null);
|
|
|
|
const entry = getCacheEntry(query, 3600);
|
|
expect(entry).not.toBeNull();
|
|
expect(entry?.result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('matchesDNSBL', () => {
|
|
it('should match by index', () => {
|
|
const config: DNSBLConfig = {
|
|
cfgNum: 1,
|
|
server: 'dnsbl.example.com',
|
|
index: '2,3,4',
|
|
};
|
|
|
|
expect(matchesDNSBL(['127.0.0.2'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.3'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.4'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.5'], config)).toBe(false);
|
|
expect(matchesDNSBL(['127.0.0.1'], config)).toBe(false);
|
|
});
|
|
|
|
it('should match by bitmask', () => {
|
|
const config: DNSBLConfig = {
|
|
cfgNum: 1,
|
|
server: 'dnsbl.example.com',
|
|
bitmask: '2', // Binary: 010
|
|
};
|
|
|
|
expect(matchesDNSBL(['127.0.0.2'], config)).toBe(true); // 010 & 010 = 010
|
|
expect(matchesDNSBL(['127.0.0.3'], config)).toBe(true); // 011 & 010 = 010
|
|
expect(matchesDNSBL(['127.0.0.6'], config)).toBe(true); // 110 & 010 = 010
|
|
expect(matchesDNSBL(['127.0.0.1'], config)).toBe(false); // 001 & 010 = 000
|
|
expect(matchesDNSBL(['127.0.0.4'], config)).toBe(false); // 100 & 010 = 000
|
|
});
|
|
|
|
it('should match multiple bitmasks', () => {
|
|
const config: DNSBLConfig = {
|
|
cfgNum: 1,
|
|
server: 'dnsbl.example.com',
|
|
bitmask: '2,4', // Match if bit 1 or bit 2 set
|
|
};
|
|
|
|
expect(matchesDNSBL(['127.0.0.2'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.4'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.6'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.1'], config)).toBe(false);
|
|
});
|
|
|
|
it('should match any result if no index or bitmask', () => {
|
|
const config: DNSBLConfig = {
|
|
cfgNum: 1,
|
|
server: 'dnsbl.example.com',
|
|
};
|
|
|
|
expect(matchesDNSBL(['127.0.0.1'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.255'], config)).toBe(true);
|
|
});
|
|
|
|
it('should not match empty results', () => {
|
|
const config: DNSBLConfig = {
|
|
cfgNum: 1,
|
|
server: 'dnsbl.example.com',
|
|
index: '2',
|
|
};
|
|
|
|
expect(matchesDNSBL([], config)).toBe(false);
|
|
});
|
|
|
|
it('should match if any result matches (multiple results)', () => {
|
|
const config: DNSBLConfig = {
|
|
cfgNum: 1,
|
|
server: 'dnsbl.example.com',
|
|
index: '4',
|
|
};
|
|
|
|
expect(matchesDNSBL(['127.0.0.2', '127.0.0.4'], config)).toBe(true);
|
|
expect(matchesDNSBL(['127.0.0.1', '127.0.0.2'], config)).toBe(false);
|
|
});
|
|
|
|
it('should handle invalid result IPs gracefully', () => {
|
|
const config: DNSBLConfig = {
|
|
cfgNum: 1,
|
|
server: 'dnsbl.example.com',
|
|
index: '2',
|
|
};
|
|
|
|
expect(matchesDNSBL(['invalid', '127.0.0.2'], config)).toBe(true);
|
|
expect(matchesDNSBL(['invalid'], config)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('parseQuery', () => {
|
|
it('should parse a valid DNSBL query', () => {
|
|
const result = parseQuery('10.1.168.192.dnsbl.example.com');
|
|
expect(result).not.toBeNull();
|
|
expect(result?.ip).toBe('192.168.1.10');
|
|
expect(result?.server).toBe('dnsbl.example.com');
|
|
});
|
|
|
|
it('should handle multi-part server names', () => {
|
|
const result = parseQuery('1.0.0.127.zen.spamhaus.org');
|
|
expect(result).not.toBeNull();
|
|
expect(result?.ip).toBe('127.0.0.1');
|
|
expect(result?.server).toBe('zen.spamhaus.org');
|
|
});
|
|
|
|
it('should return null for invalid queries', () => {
|
|
expect(parseQuery('invalid')).toBeNull();
|
|
expect(parseQuery('dnsbl.example.com')).toBeNull();
|
|
expect(parseQuery('')).toBeNull();
|
|
});
|
|
});
|
|
});
|