This commit was merged in pull request #12.
This commit is contained in:
@@ -2,11 +2,13 @@ package output
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hits/ExploreDNS/internal/dns"
|
||||
"github.com/hits/ExploreDNS/internal/traverse"
|
||||
miekgdns "github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func TestTextFormatterProgressIndentation(t *testing.T) {
|
||||
@@ -63,3 +65,314 @@ func TestAttachHooksRespectsShowFlags(t *testing.T) {
|
||||
t.Fatal("expected progress output when ShowProgress is true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteResolve(t *testing.T) {
|
||||
ref := traverse.NewReferral("example.com.", dns.TypeA, ".", 0, 1.0, nil)
|
||||
server := net.ParseIP("198.41.0.4")
|
||||
resp := &traverse.Response{Server: server, Type: traverse.RespAnswer}
|
||||
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
|
||||
// EventStart - should write line
|
||||
if err := f.WriteResolve(traverse.TraversalEvent{
|
||||
Stage: traverse.EventStart,
|
||||
Result: traverse.TraversalResult{Referral: ref, Response: resp},
|
||||
}); err != nil {
|
||||
t.Fatalf("WriteResolve EventStart: %v", err)
|
||||
}
|
||||
if buf.Len() == 0 {
|
||||
t.Error("expected output for WriteResolve EventStart")
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
// EventComplete - should write nothing
|
||||
if err := f.WriteResolve(traverse.TraversalEvent{
|
||||
Stage: traverse.EventComplete,
|
||||
Result: traverse.TraversalResult{Referral: ref, Response: resp},
|
||||
}); err != nil {
|
||||
t.Fatalf("WriteResolve EventComplete: %v", err)
|
||||
}
|
||||
if buf.Len() != 0 {
|
||||
t.Error("expected no output for WriteResolve EventComplete")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteResult(t *testing.T) {
|
||||
ref := traverse.NewReferral("example.com.", dns.TypeA, ".", 0, 1.0, nil)
|
||||
server := net.ParseIP("198.41.0.4")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
respType traverse.ResponseType
|
||||
msg *dns.DecodedResponse
|
||||
errorMsg string
|
||||
}{
|
||||
{"answer", traverse.RespAnswer, &dns.DecodedResponse{
|
||||
Answers: []miekgdns.RR{
|
||||
&miekgdns.A{Hdr: miekgdns.RR_Header{Name: "example.com.", Rrtype: dns.TypeA, Class: miekgdns.ClassINET}, A: net.ParseIP("1.2.3.4")},
|
||||
},
|
||||
}, ""},
|
||||
{"nodata", traverse.RespNODATA, nil, ""},
|
||||
{"nxdomain", traverse.RespNXDOMAIN, nil, ""},
|
||||
{"servfail", traverse.RespSERVFAIL, nil, ""},
|
||||
{"refused", traverse.RespREFUSED, nil, ""},
|
||||
{"notimp", traverse.RespNOTIMPL, nil, ""},
|
||||
{"cname_loop", traverse.RespCNAMELoop, nil, "loop detected"},
|
||||
{"error", traverse.RespError, nil, "something went wrong"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
|
||||
resp := &traverse.Response{
|
||||
Referral: ref,
|
||||
Server: server,
|
||||
Type: tc.respType,
|
||||
Decoded: tc.msg,
|
||||
ErrorMessage: tc.errorMsg,
|
||||
}
|
||||
result := traverse.TraversalResult{Referral: ref, Response: resp}
|
||||
if err := f.WriteResult(result); err != nil {
|
||||
t.Fatalf("WriteResult %q: %v", tc.name, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteResultNilResponse(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
if err := f.WriteResult(traverse.TraversalResult{Referral: nil, Response: nil}); err != nil {
|
||||
t.Fatalf("WriteResult nil: %v", err)
|
||||
}
|
||||
if buf.Len() != 0 {
|
||||
t.Error("expected no output for nil result")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteResultAnswerMultipleRRs(t *testing.T) {
|
||||
ref := traverse.NewReferral("example.com.", dns.TypeA, ".", 0, 0.5, nil)
|
||||
resp := &traverse.Response{
|
||||
Referral: ref,
|
||||
Server: net.ParseIP("1.2.3.4"),
|
||||
Type: traverse.RespAnswer,
|
||||
Decoded: &dns.DecodedResponse{
|
||||
Answers: []miekgdns.RR{
|
||||
&miekgdns.A{Hdr: miekgdns.RR_Header{Name: "example.com.", Rrtype: dns.TypeA, Class: miekgdns.ClassINET}, A: net.ParseIP("1.2.3.4")},
|
||||
&miekgdns.A{Hdr: miekgdns.RR_Header{Name: "example.com.", Rrtype: dns.TypeA, Class: miekgdns.ClassINET}, A: net.ParseIP("5.6.7.8")},
|
||||
},
|
||||
},
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
if err := f.WriteResult(traverse.TraversalResult{Referral: ref, Response: resp}); err != nil {
|
||||
t.Fatalf("WriteResult: %v", err)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "/") {
|
||||
t.Errorf("expected '/' separator for multiple answers, got: %q", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteSummaryWithServersAndResults(t *testing.T) {
|
||||
ref := traverse.NewReferral("example.com.", dns.TypeA, "com.", 1, 1.0, nil)
|
||||
server := net.ParseIP("1.2.3.4")
|
||||
resp := &traverse.Response{
|
||||
Referral: ref,
|
||||
Server: server,
|
||||
Type: traverse.RespAnswer,
|
||||
Decoded: &dns.DecodedResponse{
|
||||
Answers: []miekgdns.RR{
|
||||
&miekgdns.A{Hdr: miekgdns.RR_Header{Name: "example.com.", Rrtype: dns.TypeA, Class: miekgdns.ClassINET}, A: net.ParseIP("1.2.3.4")},
|
||||
},
|
||||
},
|
||||
}
|
||||
results := []traverse.TraversalResult{{Referral: ref, Response: resp}}
|
||||
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
cfg.ShowServers = true
|
||||
cfg.ShowResults = true
|
||||
cfg.ShowSummaryResults = true
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
if err := f.WriteSummary(results); err != nil {
|
||||
t.Fatalf("WriteSummary: %v", err)
|
||||
}
|
||||
out := buf.String()
|
||||
if !strings.Contains(out, "Summary:") {
|
||||
t.Errorf("expected Summary: in output, got: %q", out)
|
||||
}
|
||||
if !strings.Contains(out, "Results:") {
|
||||
t.Errorf("expected Results: in output, got: %q", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteSummaryNoResults(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.ShowServers = false
|
||||
cfg.ShowResults = false
|
||||
cfg.ShowSummaryResults = false
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
if err := f.WriteSummary(nil); err != nil {
|
||||
t.Fatalf("WriteSummary nil: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteSummaryNXDOMAIN(t *testing.T) {
|
||||
ref := traverse.NewReferral("gone.example.com.", dns.TypeA, "com.", 1, 1.0, nil)
|
||||
server := net.ParseIP("1.2.3.4")
|
||||
resp := &traverse.Response{
|
||||
Referral: ref,
|
||||
Server: server,
|
||||
Type: traverse.RespNXDOMAIN,
|
||||
}
|
||||
results := []traverse.TraversalResult{{Referral: ref, Response: resp}}
|
||||
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
cfg.ShowServers = true
|
||||
cfg.ShowResults = true
|
||||
cfg.ShowSummaryResults = true
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
if err := f.WriteSummary(results); err != nil {
|
||||
t.Fatalf("WriteSummary: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatReferralLineVerbose(t *testing.T) {
|
||||
root := traverse.NewReferral("example.com.", dns.TypeA, ".", 0, 1.0, nil)
|
||||
child := traverse.NewReferral("example.com.", dns.TypeA, "com.", 1, 1.0, root)
|
||||
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
cfg.Verbose = true
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
|
||||
event := traverse.TraversalEvent{
|
||||
Stage: traverse.EventStart,
|
||||
Result: traverse.TraversalResult{Referral: child},
|
||||
}
|
||||
if err := f.WriteProgress(event); err != nil {
|
||||
t.Fatalf("WriteProgress verbose: %v", err)
|
||||
}
|
||||
out := buf.String()
|
||||
if !strings.Contains(out, "com") {
|
||||
t.Errorf("expected bailiwick in verbose output, got: %q", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatReferralLineVerboseResolve(t *testing.T) {
|
||||
ref := traverse.NewReferral("example.com.", dns.TypeA, "com.", 1, 1.0, nil)
|
||||
server := net.ParseIP("1.2.3.4")
|
||||
resp := &traverse.Response{Server: server, Type: traverse.RespAnswer}
|
||||
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
cfg.Verbose = true
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
|
||||
if err := f.WriteResolve(traverse.TraversalEvent{
|
||||
Stage: traverse.EventStart,
|
||||
Result: traverse.TraversalResult{Referral: ref, Response: resp},
|
||||
}); err != nil {
|
||||
t.Fatalf("WriteResolve verbose: %v", err)
|
||||
}
|
||||
if buf.Len() == 0 {
|
||||
t.Error("expected output for verbose WriteResolve")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriteProgressNoAddresses(t *testing.T) {
|
||||
// Test the "resolving" suffix when referral has no addresses
|
||||
ref := traverse.NewReferral("example.com.", dns.TypeA, ".", 0, 1.0, nil)
|
||||
// No addresses set, so HasAddresses() returns false
|
||||
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = false
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
if err := f.WriteProgress(traverse.TraversalEvent{
|
||||
Stage: traverse.EventStart,
|
||||
Result: traverse.TraversalResult{Referral: ref},
|
||||
}); err != nil {
|
||||
t.Fatalf("WriteProgress: %v", err)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "resolving") {
|
||||
t.Errorf("expected 'resolving' suffix when no addresses, got: %q", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestColorize(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
cfg := DefaultConfig()
|
||||
cfg.Color = true
|
||||
f := newTextFormatter(cfg, &buf)
|
||||
|
||||
colored := f.colorize("hello", colorGreen)
|
||||
if colored == "hello" {
|
||||
t.Error("expected colorized output with Color=true")
|
||||
}
|
||||
|
||||
cfg.Color = false
|
||||
f2 := newTextFormatter(cfg, &buf)
|
||||
plain := f2.colorize("hello", colorGreen)
|
||||
if plain != "hello" {
|
||||
t.Errorf("expected plain text with Color=false, got %q", plain)
|
||||
}
|
||||
|
||||
// Empty color
|
||||
empty := f.colorize("hello", "")
|
||||
if empty != "hello" {
|
||||
t.Errorf("expected plain text for empty color, got %q", empty)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReferralServerLabelFallbacks(t *testing.T) {
|
||||
// With server IP in response
|
||||
ref := traverse.NewReferral("example.com.", dns.TypeA, ".", 0, 1.0, nil)
|
||||
resp := &traverse.Response{Server: net.ParseIP("1.2.3.4")}
|
||||
label := referralServerLabel(ref, resp)
|
||||
if label != "1.2.3.4" {
|
||||
t.Errorf("expected '1.2.3.4', got %q", label)
|
||||
}
|
||||
|
||||
// With addresses in referral, no response server
|
||||
ref2 := traverse.NewReferral("example.com.", dns.TypeA, "ns1.example.com.", 0, 1.0, nil)
|
||||
ref2.Addresses = []net.IP{net.ParseIP("5.6.7.8")}
|
||||
label2 := referralServerLabel(ref2, nil)
|
||||
if label2 != "5.6.7.8" {
|
||||
t.Errorf("expected '5.6.7.8', got %q", label2)
|
||||
}
|
||||
|
||||
// With NSName
|
||||
ref3 := &traverse.Referral{
|
||||
Name: "example.com.",
|
||||
NSName: "ns1.example.com.",
|
||||
Bailiwick: ".",
|
||||
}
|
||||
label3 := referralServerLabel(ref3, nil)
|
||||
if label3 != "ns1.example.com." {
|
||||
t.Errorf("expected NSName, got %q", label3)
|
||||
}
|
||||
|
||||
// With non-root bailiwick, no addresses, no NSName
|
||||
ref4 := traverse.NewReferral("example.com.", dns.TypeA, "com.", 0, 1.0, nil)
|
||||
label4 := referralServerLabel(ref4, nil)
|
||||
if label4 != "com" {
|
||||
t.Errorf("expected 'com', got %q", label4)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user