Fix short flags, AllowTCP wiring, invalid root server error, add config tests
CI / test (pull_request) Failing after 2m14s

- Register -v/-q short flag aliases sharing the same bool variable as
  --verbose/--quiet so both forms work identically
- Register -d and -dd flags; use ParseDebugLevel() helper so -d sets
  Debug=1 and -dd sets Debug=2; remove the broken strings.Count approach
- Add AllowTCP field to dns.QueryConfig; guard TCP truncation fallback in
  QueryWithExchange and IterativeQueryWithExchange behind cfg.AllowTCP;
  wire cfg.AllowTCP from CLI config into QueryConfig in main.go
- ParseRootServer() now returns ErrInvalidRootServer instead of (nil,nil)
  when the string is non-empty but net.ParseIP fails
- Add internal/config/config_test.go covering ParseQueryType, ParseUDPSize,
  Validate, GetDomain, ParseRootServer, ParseDebugLevel, and the
  --always-tcp/--allow-tcp cross-check
- Add TestQueryNoTCPFallbackWhenDisabled to dns/query_test.go
- Update existing truncation tests to set AllowTCP:true
- Add TODO comments on display flags not yet wired to output layer

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
Gary Hansen
2026-06-08 01:29:46 +10:00
co-authored by Copilot multica-agent
parent d66dcbe067
commit 93c5ca7bba
5 changed files with 332 additions and 45 deletions
+31 -21
View File
@@ -5,7 +5,6 @@ import (
"flag"
"fmt"
"os"
"strings"
"time"
"github.com/hits/ExploreDNS/internal/config"
@@ -27,22 +26,42 @@ func main() {
maxDepth := flag.Int("max-depth", cfg.MaxDepth, "Max traversal depth (1-100)")
retries := flag.Int("retries", cfg.Retries, "Retry count (0-10)")
fast := flag.Bool("fast", cfg.Fast, "Fast mode: reuse earlier branch cache")
verbose := flag.Bool("verbose", cfg.Verbose, "Verbose output")
debugFlag := flag.Bool("debug", false, "Debug mode (stackable: -dd for library debug)")
quiet := flag.Bool("quiet", cfg.Quiet, "Suppress supplementary info")
// Verbose: long and short form share the same variable.
var verboseVal bool
flag.BoolVar(&verboseVal, "verbose", cfg.Verbose, "Verbose output")
flag.BoolVar(&verboseVal, "v", cfg.Verbose, "Verbose output (shorthand)")
// Debug: -d sets level 1, -dd sets level 2 (library debug).
var dFlag, ddFlag bool
flag.BoolVar(&dFlag, "d", false, "Debug mode (stackable: -dd for library debug)")
flag.BoolVar(&dFlag, "debug", false, "Debug mode")
flag.BoolVar(&ddFlag, "dd", false, "Library debug mode (equivalent to -d -d)")
// Quiet: long and short form share the same variable.
var quietVal bool
flag.BoolVar(&quietVal, "quiet", cfg.Quiet, "Suppress supplementary info")
flag.BoolVar(&quietVal, "q", cfg.Quiet, "Suppress supplementary info (shorthand)")
// TODO: ShowProgress is parsed but not yet wired to the traversal/output layer.
showProgress := flag.Bool("show-progress", cfg.ShowProgress, "Show traversal progress")
noShowProgress := flag.Bool("no-show-progress", false, "Hide traversal progress")
// TODO: ShowResolves is parsed but not yet wired to the traversal/output layer.
showResolves := flag.Bool("show-resolves", cfg.ShowResolves, "Show glue resolution details")
noShowResolves := flag.Bool("no-show-resolves", false, "Hide glue resolution details")
// TODO: ShowServers is parsed but not yet wired to the traversal/output layer.
showServers := flag.Bool("show-servers", cfg.ShowServers, "Show servers queried")
noShowServers := flag.Bool("no-show-servers", false, "Hide servers queried")
// TODO: ShowVersions is parsed but not yet wired to the traversal/output layer.
showVersions := flag.Bool("show-versions", cfg.ShowVersions, "Show server versions")
noShowVersions := flag.Bool("no-show-versions", false, "Hide server versions")
// TODO: ShowAllStats is parsed but not yet wired to the traversal/output layer.
showAllStats := flag.Bool("show-all-stats", cfg.ShowAllStats, "Show all statistics")
noShowAllStats := flag.Bool("no-show-all-stats", false, "Hide all statistics")
// TODO: ShowResults is partially wired; full structured output is pending.
showResults := flag.Bool("show-results", cfg.ShowResults, "Show query results")
noShowResults := flag.Bool("no-show-results", false, "Hide query results")
// TODO: ShowSummaryResults is parsed but not yet wired to the traversal/output layer.
showSummaryResults := flag.Bool("show-summary-results", cfg.ShowSummaryResults, "Show summary of results")
noShowSummaryResults := flag.Bool("no-show-summary-results", false, "Hide summary of results")
@@ -52,16 +71,6 @@ func main() {
args := flag.Args()
debugLevel := 0
for _, arg := range os.Args[1:] {
if strings.Count(arg, "-d") > 0 || strings.Count(arg, "-dd") > 0 {
debugLevel = strings.Count(arg, "-d") + strings.Count(arg, "-dd")
}
}
if *debugFlag {
debugLevel++
}
cfg.QueryType = *queryType
cfg.RootServer = *rootServer
cfg.AllRootServers = *allRootServers
@@ -73,9 +82,9 @@ func main() {
cfg.MaxDepth = *maxDepth
cfg.Retries = *retries
cfg.Fast = *fast
cfg.Verbose = *verbose
cfg.Debug = debugLevel
cfg.Quiet = *quiet
cfg.Verbose = verboseVal
cfg.Debug = config.ParseDebugLevel(dFlag, ddFlag)
cfg.Quiet = quietVal
if *noShowProgress {
cfg.ShowProgress = false
@@ -142,10 +151,11 @@ func main() {
}
queryConfig := &dns.QueryConfig{
UDPSize: cfg.UDPSize,
Timeout: 5 * time.Second,
Retries: cfg.Retries,
UseTCP: cfg.AlwaysTCP,
UDPSize: cfg.UDPSize,
Timeout: 5 * time.Second,
Retries: cfg.Retries,
UseTCP: cfg.AlwaysTCP,
AllowTCP: cfg.AllowTCP,
}
rootConfig := &dns.RootDiscoveryConfig{