|
|
@@ -5,6 +5,7 @@
|
|
|
package dnsmessage
|
|
|
|
|
|
import (
|
|
|
+ "bytes"
|
|
|
"fmt"
|
|
|
"net"
|
|
|
"reflect"
|
|
|
@@ -12,6 +13,14 @@ import (
|
|
|
"testing"
|
|
|
)
|
|
|
|
|
|
+func mustNewName(name string) Name {
|
|
|
+ n, err := NewName(name)
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ return n
|
|
|
+}
|
|
|
+
|
|
|
func (m *Message) String() string {
|
|
|
s := fmt.Sprintf("Message: %#v\n", &m.Header)
|
|
|
if len(m.Questions) > 0 {
|
|
|
@@ -41,9 +50,17 @@ func (m *Message) String() string {
|
|
|
return s
|
|
|
}
|
|
|
|
|
|
+func TestNameString(t *testing.T) {
|
|
|
+ want := "foo"
|
|
|
+ name := mustNewName(want)
|
|
|
+ if got := fmt.Sprint(name); got != want {
|
|
|
+ t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func TestQuestionPackUnpack(t *testing.T) {
|
|
|
want := Question{
|
|
|
- Name: ".",
|
|
|
+ Name: mustNewName("."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
}
|
|
|
@@ -68,16 +85,42 @@ func TestQuestionPackUnpack(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func TestName(t *testing.T) {
|
|
|
+ tests := []string{
|
|
|
+ "",
|
|
|
+ ".",
|
|
|
+ "google..com",
|
|
|
+ "google.com",
|
|
|
+ "google..com.",
|
|
|
+ "google.com.",
|
|
|
+ ".google.com.",
|
|
|
+ "www..google.com.",
|
|
|
+ "www.google.com.",
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, test := range tests {
|
|
|
+ n, err := NewName(test)
|
|
|
+ if err != nil {
|
|
|
+ t.Errorf("Creating name for %q: %v", test, err)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if ns := n.String(); ns != test {
|
|
|
+ t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func TestNamePackUnpack(t *testing.T) {
|
|
|
tests := []struct {
|
|
|
in string
|
|
|
want string
|
|
|
err error
|
|
|
}{
|
|
|
- {"", ".", nil},
|
|
|
+ {"", "", errNonCanonicalName},
|
|
|
{".", ".", nil},
|
|
|
- {"google..com", "", errZeroSegLen},
|
|
|
- {"google.com", "google.com.", nil},
|
|
|
+ {"google..com", "", errNonCanonicalName},
|
|
|
+ {"google.com", "", errNonCanonicalName},
|
|
|
{"google..com.", "", errZeroSegLen},
|
|
|
{"google.com.", "google.com.", nil},
|
|
|
{".google.com.", "", errZeroSegLen},
|
|
|
@@ -86,29 +129,32 @@ func TestNamePackUnpack(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
for _, test := range tests {
|
|
|
- buf, err := packName(make([]byte, 0, 30), test.in, map[string]int{})
|
|
|
+ in := mustNewName(test.in)
|
|
|
+ want := mustNewName(test.want)
|
|
|
+ buf, err := in.pack(make([]byte, 0, 30), map[string]int{})
|
|
|
if err != test.err {
|
|
|
- t.Errorf("Packing of %s: got err = %v, want err = %v", test.in, err, test.err)
|
|
|
+ t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err)
|
|
|
continue
|
|
|
}
|
|
|
if test.err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- got, n, err := unpackName(buf, 0)
|
|
|
+ var got Name
|
|
|
+ n, err := got.unpack(buf, 0)
|
|
|
if err != nil {
|
|
|
- t.Errorf("Unpacking for %s failed: %v", test.in, err)
|
|
|
+ t.Errorf("Unpacking for %q failed: %v", test.in, err)
|
|
|
continue
|
|
|
}
|
|
|
if n != len(buf) {
|
|
|
t.Errorf(
|
|
|
- "Unpacked different amount than packed for %s: got n = %d, want = %d",
|
|
|
+ "Unpacked different amount than packed for %q: got n = %d, want = %d",
|
|
|
test.in,
|
|
|
n,
|
|
|
len(buf),
|
|
|
)
|
|
|
}
|
|
|
- if got != test.want {
|
|
|
- t.Errorf("Unpacking packing of %s: got = %s, want = %s", test.in, got, test.want)
|
|
|
+ if got != want {
|
|
|
+ t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -118,7 +164,7 @@ func TestDNSPackUnpack(t *testing.T) {
|
|
|
{
|
|
|
Questions: []Question{
|
|
|
{
|
|
|
- Name: ".",
|
|
|
+ Name: mustNewName("."),
|
|
|
Type: TypeAAAA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
@@ -238,32 +284,161 @@ func TestTooManyRecords(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
func TestVeryLongTxt(t *testing.T) {
|
|
|
- want := &TXTResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ want := Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeTXT,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- Txt: loremIpsum,
|
|
|
+ &TXTResource{loremIpsum},
|
|
|
}
|
|
|
- buf, err := packResource(make([]byte, 0, 8000), want, map[string]int{})
|
|
|
+ buf, err := want.pack(make([]byte, 0, 8000), map[string]int{})
|
|
|
if err != nil {
|
|
|
t.Fatal("Packing failed:", err)
|
|
|
}
|
|
|
- var hdr ResourceHeader
|
|
|
- off, err := hdr.unpack(buf, 0)
|
|
|
+ var got Resource
|
|
|
+ off, err := got.Header.unpack(buf, 0)
|
|
|
if err != nil {
|
|
|
t.Fatal("Unpacking ResourceHeader failed:", err)
|
|
|
}
|
|
|
- got, n, err := unpackResource(buf, off, hdr)
|
|
|
+ body, n, err := unpackResourceBody(buf, off, got.Header)
|
|
|
if err != nil {
|
|
|
t.Fatal("Unpacking failed:", err)
|
|
|
}
|
|
|
+ got.Body = body
|
|
|
if n != len(buf) {
|
|
|
t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
|
|
|
}
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
- t.Errorf("Got = %+v, want = %+v", got, want)
|
|
|
+ t.Errorf("Got = %#v, want = %#v", got, want)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestStartError(t *testing.T) {
|
|
|
+ tests := []struct {
|
|
|
+ name string
|
|
|
+ fn func(*Builder) error
|
|
|
+ }{
|
|
|
+ {"Questions", func(b *Builder) error { return b.StartQuestions() }},
|
|
|
+ {"Answers", func(b *Builder) error { return b.StartAnswers() }},
|
|
|
+ {"Authorities", func(b *Builder) error { return b.StartAuthorities() }},
|
|
|
+ {"Additionals", func(b *Builder) error { return b.StartAdditionals() }},
|
|
|
+ }
|
|
|
+
|
|
|
+ envs := []struct {
|
|
|
+ name string
|
|
|
+ fn func() *Builder
|
|
|
+ want error
|
|
|
+ }{
|
|
|
+ {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
|
|
|
+ {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, env := range envs {
|
|
|
+ for _, test := range tests {
|
|
|
+ if got := test.fn(env.fn()); got != env.want {
|
|
|
+ t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestBuilderResourceError(t *testing.T) {
|
|
|
+ tests := []struct {
|
|
|
+ name string
|
|
|
+ fn func(*Builder) error
|
|
|
+ }{
|
|
|
+ {"CNAMEResource", func(b *Builder) error { return b.CNAMEResource(ResourceHeader{}, CNAMEResource{}) }},
|
|
|
+ {"MXResource", func(b *Builder) error { return b.MXResource(ResourceHeader{}, MXResource{}) }},
|
|
|
+ {"NSResource", func(b *Builder) error { return b.NSResource(ResourceHeader{}, NSResource{}) }},
|
|
|
+ {"PTRResource", func(b *Builder) error { return b.PTRResource(ResourceHeader{}, PTRResource{}) }},
|
|
|
+ {"SOAResource", func(b *Builder) error { return b.SOAResource(ResourceHeader{}, SOAResource{}) }},
|
|
|
+ {"TXTResource", func(b *Builder) error { return b.TXTResource(ResourceHeader{}, TXTResource{}) }},
|
|
|
+ {"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }},
|
|
|
+ {"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }},
|
|
|
+ {"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }},
|
|
|
+ }
|
|
|
+
|
|
|
+ envs := []struct {
|
|
|
+ name string
|
|
|
+ fn func() *Builder
|
|
|
+ want error
|
|
|
+ }{
|
|
|
+ {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
|
|
|
+ {"sectionHeader", func() *Builder { return &Builder{section: sectionHeader} }, ErrNotStarted},
|
|
|
+ {"sectionQuestions", func() *Builder { return &Builder{section: sectionQuestions} }, ErrNotStarted},
|
|
|
+ {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, env := range envs {
|
|
|
+ for _, test := range tests {
|
|
|
+ if got := test.fn(env.fn()); got != env.want {
|
|
|
+ t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestFinishError(t *testing.T) {
|
|
|
+ var b Builder
|
|
|
+ want := ErrNotStarted
|
|
|
+ if _, got := b.Finish(); got != want {
|
|
|
+ t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestBuilder(t *testing.T) {
|
|
|
+ msg := largeTestMsg()
|
|
|
+ want, err := msg.Pack()
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal("Packing without builder:", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ var b Builder
|
|
|
+ b.Start(nil, msg.Header)
|
|
|
+
|
|
|
+ if err := b.StartQuestions(); err != nil {
|
|
|
+ t.Fatal("b.StartQuestions():", err)
|
|
|
+ }
|
|
|
+ for _, q := range msg.Questions {
|
|
|
+ if err := b.Question(q); err != nil {
|
|
|
+ t.Fatalf("b.Question(%#v): %v", q, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := b.StartAnswers(); err != nil {
|
|
|
+ t.Fatal("b.StartAnswers():", err)
|
|
|
+ }
|
|
|
+ for _, a := range msg.Answers {
|
|
|
+ if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil {
|
|
|
+ t.Fatalf("b.AResource(%#v): %v", a, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := b.StartAuthorities(); err != nil {
|
|
|
+ t.Fatal("b.StartAuthorities():", err)
|
|
|
+ }
|
|
|
+ for _, a := range msg.Authorities {
|
|
|
+ if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
|
|
|
+ t.Fatalf("b.NSResource(%#v): %v", a, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := b.StartAdditionals(); err != nil {
|
|
|
+ t.Fatal("b.StartAdditionals():", err)
|
|
|
+ }
|
|
|
+ for _, a := range msg.Additionals {
|
|
|
+ if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
|
|
|
+ t.Fatalf("b.TXTResource(%#v): %v", a, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ got, err := b.Finish()
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal("b.Finish():", err)
|
|
|
+ }
|
|
|
+ if !bytes.Equal(got, want) {
|
|
|
+ t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -272,32 +447,32 @@ func ExampleHeaderSearch() {
|
|
|
Header: Header{Response: true, Authoritative: true},
|
|
|
Questions: []Question{
|
|
|
{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
{
|
|
|
- Name: "bar.example.com.",
|
|
|
+ Name: mustNewName("bar.example.com."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
},
|
|
|
Answers: []Resource{
|
|
|
- &AResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- A: [4]byte{127, 0, 0, 1},
|
|
|
+ &AResource{[4]byte{127, 0, 0, 1}},
|
|
|
},
|
|
|
- &AResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("bar.example.com."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- A: [4]byte{127, 0, 0, 2},
|
|
|
+ &AResource{[4]byte{127, 0, 0, 2}},
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
@@ -323,7 +498,7 @@ func ExampleHeaderSearch() {
|
|
|
panic(err)
|
|
|
}
|
|
|
|
|
|
- if q.Name != wantName {
|
|
|
+ if q.Name.String() != wantName {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
@@ -348,23 +523,25 @@ func ExampleHeaderSearch() {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- if !strings.EqualFold(h.Name, wantName) {
|
|
|
+ if !strings.EqualFold(h.Name.String(), wantName) {
|
|
|
if err := p.SkipAnswer(); err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
continue
|
|
|
}
|
|
|
- a, err := p.Answer()
|
|
|
- if err != nil {
|
|
|
- panic(err)
|
|
|
- }
|
|
|
|
|
|
- switch r := a.(type) {
|
|
|
- default:
|
|
|
- panic(fmt.Sprintf("unknown type: %T", r))
|
|
|
- case *AResource:
|
|
|
+ switch h.Type {
|
|
|
+ case TypeA:
|
|
|
+ r, err := p.AResource()
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
gotIPs = append(gotIPs, r.A[:])
|
|
|
- case *AAAAResource:
|
|
|
+ case TypeAAAA:
|
|
|
+ r, err := p.AAAAResource()
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
gotIPs = append(gotIPs, r.AAAA[:])
|
|
|
}
|
|
|
}
|
|
|
@@ -376,68 +553,223 @@ func ExampleHeaderSearch() {
|
|
|
// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
|
|
|
}
|
|
|
|
|
|
+func BenchmarkParsing(b *testing.B) {
|
|
|
+ b.ReportAllocs()
|
|
|
+
|
|
|
+ name := mustNewName("foo.bar.example.com.")
|
|
|
+ msg := Message{
|
|
|
+ Header: Header{Response: true, Authoritative: true},
|
|
|
+ Questions: []Question{
|
|
|
+ {
|
|
|
+ Name: name,
|
|
|
+ Type: TypeA,
|
|
|
+ Class: ClassINET,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ Answers: []Resource{
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: name,
|
|
|
+ Class: ClassINET,
|
|
|
+ },
|
|
|
+ &AResource{[4]byte{}},
|
|
|
+ },
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: name,
|
|
|
+ Class: ClassINET,
|
|
|
+ },
|
|
|
+ &AAAAResource{[16]byte{}},
|
|
|
+ },
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: name,
|
|
|
+ Class: ClassINET,
|
|
|
+ },
|
|
|
+ &CNAMEResource{name},
|
|
|
+ },
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: name,
|
|
|
+ Class: ClassINET,
|
|
|
+ },
|
|
|
+ &NSResource{name},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ buf, err := msg.Pack()
|
|
|
+ if err != nil {
|
|
|
+ b.Fatal("msg.Pack():", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ for i := 0; i < b.N; i++ {
|
|
|
+ var p Parser
|
|
|
+ if _, err := p.Start(buf); err != nil {
|
|
|
+ b.Fatal("p.Start(buf):", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ for {
|
|
|
+ _, err := p.Question()
|
|
|
+ if err == ErrSectionDone {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ b.Fatal("p.Question():", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for {
|
|
|
+ h, err := p.AnswerHeader()
|
|
|
+ if err == ErrSectionDone {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ switch h.Type {
|
|
|
+ case TypeA:
|
|
|
+ if _, err := p.AResource(); err != nil {
|
|
|
+ b.Fatal("p.AResource():", err)
|
|
|
+ }
|
|
|
+ case TypeAAAA:
|
|
|
+ if _, err := p.AAAAResource(); err != nil {
|
|
|
+ b.Fatal("p.AAAAResource():", err)
|
|
|
+ }
|
|
|
+ case TypeCNAME:
|
|
|
+ if _, err := p.CNAMEResource(); err != nil {
|
|
|
+ b.Fatal("p.CNAMEResource():", err)
|
|
|
+ }
|
|
|
+ case TypeNS:
|
|
|
+ if _, err := p.NSResource(); err != nil {
|
|
|
+ b.Fatal("p.NSResource():", err)
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ b.Fatalf("unknown type: %T", h)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func BenchmarkBuilding(b *testing.B) {
|
|
|
+ b.ReportAllocs()
|
|
|
+
|
|
|
+ name := mustNewName("foo.bar.example.com.")
|
|
|
+ buf := make([]byte, 0, packStartingCap)
|
|
|
+
|
|
|
+ for i := 0; i < b.N; i++ {
|
|
|
+ var bld Builder
|
|
|
+ bld.StartWithoutCompression(buf, Header{Response: true, Authoritative: true})
|
|
|
+
|
|
|
+ if err := bld.StartQuestions(); err != nil {
|
|
|
+ b.Fatal("bld.StartQuestions():", err)
|
|
|
+ }
|
|
|
+ q := Question{
|
|
|
+ Name: name,
|
|
|
+ Type: TypeA,
|
|
|
+ Class: ClassINET,
|
|
|
+ }
|
|
|
+ if err := bld.Question(q); err != nil {
|
|
|
+ b.Fatalf("bld.Question(%+v): %v", q, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ hdr := ResourceHeader{
|
|
|
+ Name: name,
|
|
|
+ Class: ClassINET,
|
|
|
+ }
|
|
|
+ if err := bld.StartAnswers(); err != nil {
|
|
|
+ b.Fatal("bld.StartQuestions():", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ ar := AResource{[4]byte{}}
|
|
|
+ if err := bld.AResource(hdr, ar); err != nil {
|
|
|
+ b.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ aaar := AAAAResource{[16]byte{}}
|
|
|
+ if err := bld.AAAAResource(hdr, aaar); err != nil {
|
|
|
+ b.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ cnr := CNAMEResource{name}
|
|
|
+ if err := bld.CNAMEResource(hdr, cnr); err != nil {
|
|
|
+ b.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ nsr := NSResource{name}
|
|
|
+ if err := bld.NSResource(hdr, nsr); err != nil {
|
|
|
+ b.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if _, err := bld.Finish(); err != nil {
|
|
|
+ b.Fatal("bld.Finish():", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func largeTestMsg() Message {
|
|
|
return Message{
|
|
|
Header: Header{Response: true, Authoritative: true},
|
|
|
Questions: []Question{
|
|
|
{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
},
|
|
|
Answers: []Resource{
|
|
|
- &AResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- A: [4]byte{127, 0, 0, 1},
|
|
|
+ &AResource{[4]byte{127, 0, 0, 1}},
|
|
|
},
|
|
|
- &AResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeA,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- A: [4]byte{127, 0, 0, 2},
|
|
|
+ &AResource{[4]byte{127, 0, 0, 2}},
|
|
|
},
|
|
|
},
|
|
|
Authorities: []Resource{
|
|
|
- &NSResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeNS,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- NS: "ns1.example.com.",
|
|
|
+ &NSResource{mustNewName("ns1.example.com.")},
|
|
|
},
|
|
|
- &NSResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeNS,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- NS: "ns2.example.com.",
|
|
|
+ &NSResource{mustNewName("ns2.example.com.")},
|
|
|
},
|
|
|
},
|
|
|
Additionals: []Resource{
|
|
|
- &TXTResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeTXT,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- Txt: "So Long, and Thanks for All the Fish",
|
|
|
+ &TXTResource{"So Long, and Thanks for All the Fish"},
|
|
|
},
|
|
|
- &TXTResource{
|
|
|
- ResourceHeader: ResourceHeader{
|
|
|
- Name: "foo.bar.example.com.",
|
|
|
+ Resource{
|
|
|
+ ResourceHeader{
|
|
|
+ Name: mustNewName("foo.bar.example.com."),
|
|
|
Type: TypeTXT,
|
|
|
Class: ClassINET,
|
|
|
},
|
|
|
- Txt: "Hamster Huey and the Gooey Kablooie",
|
|
|
+ &TXTResource{"Hamster Huey and the Gooey Kablooie"},
|
|
|
},
|
|
|
},
|
|
|
}
|