Test that all 9 DNS modes produce valid output files containing domains from both the domains.txt and hosts.txt test data files. -- Testcase -- import adb from 'adblock-fast'; import { readfile, dirname, mkdir } from 'fs'; let ti = adb._test_internals; let modes = [ 'dnsmasq.servers', 'dnsmasq.conf', 'dnsmasq.ipset', 'dnsmasq.nftset', 'dnsmasq.addnhosts', 'smartdns.domainset', 'smartdns.ipset', 'smartdns.nftset', 'unbound.adb_list', ]; // Known-good domains that MUST appear in every output let must_have = [ 'ad.doubleclick.test.example.com', 'tracker.analytics.test.example.com', 'common-shared-1.test.example.com', 'common-shared-10.test.example.com', 'adhost-zero-1.test.example.org', 'adhost-loopback-1.test.example.org', 'parent-dedup-1.test.example.com', ]; // Domains that MUST NOT appear (invalid entries or subdomain-deduped) let must_not_have = [ 'localhost', 'nodot', 'child.parent-dedup-1.test.example.com', 'sub.child.parent-dedup-2.test.example.com', 'deep.sub.parent-dedup-3.test.example.com', ]; let results = []; for (let mode in modes) { // Reset module state for each mode ti.env._loaded = false; ti.env.dnsmasq_features = ''; ti.env._detected = false; ti.env.dnsmasq_ubus = null; ti.status_data.errors = []; ti.status_data.warnings = []; ti.status_data.status = ''; ti.status_data.message = ''; ti.status_data.stats = ''; // Load config from mock UCI adb.env.load_config(); // Override DNS mode via set_cfg (load() reassigns cfg, so direct ref is stale) ti.set_cfg('dns', mode); ti.set_cfg('enabled', true); ti.set_cfg('dnsmasq_sanity_check', false); ti.set_cfg('dnsmasq_validity_check', false); ti.set_cfg('heartbeat_domain', null); ti.set_cfg('config_update_enabled', false); ti.set_cfg('update_config_sizes', false); ti.env.dns_set_output_values(mode); // Collect file_url sections ti.append_urls(); // Ensure output directory exists let out_file = ti.dns_output.file; let out_dir = dirname(out_file); mkdir(out_dir); // Run the download and processing pipeline let ok = ti.download_lists(); if (!ok) { push(results, sprintf('%s: FAIL (download_lists returned false)', mode)); if (length(ti.status_data.errors)) push(results, sprintf(' errors: %J', ti.status_data.errors)); continue; } // Read output let content = readfile(out_file); if (!content || !length(content)) { push(results, sprintf('%s: FAIL (empty output file %s)', mode, out_file)); continue; } let lines = filter(split(content, '\n'), l => length(l) > 0); let line_count = length(lines); // Extract domains using the mode's parse_filter let dm = ti.dns_modes[mode]; let domains = {}; let bad_format = 0; for (let line in lines) { let domain; switch (mode) { case 'dnsmasq.servers': let m1 = match(line, /^server=\/([^\/]+)\/$/); domain = m1 ? m1[1] : null; break; case 'dnsmasq.conf': let m2 = match(line, /^local=\/([^\/]+)\/$/); domain = m2 ? m2[1] : null; break; case 'dnsmasq.ipset': let m3 = match(line, /^ipset=\/([^\/]+)\/adb$/); domain = m3 ? m3[1] : null; break; case 'dnsmasq.nftset': let m4 = match(line, /^nftset=\/([^\/]+)\/4#/); domain = m4 ? m4[1] : null; break; case 'dnsmasq.addnhosts': let m5 = match(line, /^127\.0\.0\.1 (.+)$/); domain = m5 ? m5[1] : null; break; case 'smartdns.domainset': case 'smartdns.ipset': case 'smartdns.nftset': domain = match(line, /^[a-zA-Z0-9._-]+$/) ? line : null; break; case 'unbound.adb_list': let m6 = match(line, /^local-zone: "([^"]+)\." always_nxdomain$/); domain = m6 ? m6[1] : null; if (!domain && line == 'server:') domain = '__header__'; break; } if (domain && domain != '__header__') domains[domain] = true; else if (!domain) bad_format++; } let domain_count = length(keys(domains)); // Check must_have domains let missing = []; for (let d in must_have) { if (!domains[d]) push(missing, d); } // Check must_not_have domains let unwanted = []; for (let d in must_not_have) { if (domains[d]) push(unwanted, d); } // dnsmasq.addnhosts doesn't do subdomain dedup (not in needs_optimization list) let skip_dedup = (mode == 'dnsmasq.addnhosts'); if (skip_dedup) { unwanted = filter(unwanted, d => d != 'child.parent-dedup-1.test.example.com' && d != 'sub.child.parent-dedup-2.test.example.com' && d != 'deep.sub.parent-dedup-3.test.example.com'); } if (length(missing) == 0 && length(unwanted) == 0 && bad_format == 0 && domain_count > 100) push(results, sprintf('%s: PASS (%d domains)', mode, domain_count)); else { let detail = sprintf('%s: FAIL (%d domains, %d bad_format', mode, domain_count, bad_format); if (length(missing)) detail += sprintf(', missing: %J', missing); if (length(unwanted)) detail += sprintf(', unwanted: %J', unwanted); detail += ')'; push(results, detail); } } print(join('\n', results) + '\n'); -- End -- -- Expect stdout -- dnsmasq.servers: PASS (162 domains) dnsmasq.conf: PASS (162 domains) dnsmasq.ipset: PASS (162 domains) dnsmasq.nftset: PASS (162 domains) dnsmasq.addnhosts: PASS (165 domains) smartdns.domainset: PASS (162 domains) smartdns.ipset: PASS (162 domains) smartdns.nftset: PASS (162 domains) unbound.adb_list: PASS (162 domains) -- End --