OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / dns / dnsmessage / message_test.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package dnsmessage
6
7 import (
8         "bytes"
9         "fmt"
10         "reflect"
11         "testing"
12 )
13
14 func mustNewName(name string) Name {
15         n, err := NewName(name)
16         if err != nil {
17                 panic(err)
18         }
19         return n
20 }
21
22 func (m *Message) String() string {
23         s := fmt.Sprintf("Message: %#v\n", &m.Header)
24         if len(m.Questions) > 0 {
25                 s += "-- Questions\n"
26                 for _, q := range m.Questions {
27                         s += fmt.Sprintf("%#v\n", q)
28                 }
29         }
30         if len(m.Answers) > 0 {
31                 s += "-- Answers\n"
32                 for _, a := range m.Answers {
33                         s += fmt.Sprintf("%#v\n", a)
34                 }
35         }
36         if len(m.Authorities) > 0 {
37                 s += "-- Authorities\n"
38                 for _, ns := range m.Authorities {
39                         s += fmt.Sprintf("%#v\n", ns)
40                 }
41         }
42         if len(m.Additionals) > 0 {
43                 s += "-- Additionals\n"
44                 for _, e := range m.Additionals {
45                         s += fmt.Sprintf("%#v\n", e)
46                 }
47         }
48         return s
49 }
50
51 func TestNameString(t *testing.T) {
52         want := "foo"
53         name := mustNewName(want)
54         if got := fmt.Sprint(name); got != want {
55                 t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want)
56         }
57 }
58
59 func TestQuestionPackUnpack(t *testing.T) {
60         want := Question{
61                 Name:  mustNewName("."),
62                 Type:  TypeA,
63                 Class: ClassINET,
64         }
65         buf, err := want.pack(make([]byte, 1, 50), map[string]int{})
66         if err != nil {
67                 t.Fatal("Packing failed:", err)
68         }
69         var p Parser
70         p.msg = buf
71         p.header.questions = 1
72         p.section = sectionQuestions
73         p.off = 1
74         got, err := p.Question()
75         if err != nil {
76                 t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:]))
77         }
78         if p.off != len(buf) {
79                 t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf))
80         }
81         if !reflect.DeepEqual(got, want) {
82                 t.Errorf("Got = %+v, want = %+v", got, want)
83         }
84 }
85
86 func TestName(t *testing.T) {
87         tests := []string{
88                 "",
89                 ".",
90                 "google..com",
91                 "google.com",
92                 "google..com.",
93                 "google.com.",
94                 ".google.com.",
95                 "www..google.com.",
96                 "www.google.com.",
97         }
98
99         for _, test := range tests {
100                 n, err := NewName(test)
101                 if err != nil {
102                         t.Errorf("Creating name for %q: %v", test, err)
103                         continue
104                 }
105                 if ns := n.String(); ns != test {
106                         t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test)
107                         continue
108                 }
109         }
110 }
111
112 func TestNamePackUnpack(t *testing.T) {
113         tests := []struct {
114                 in   string
115                 want string
116                 err  error
117         }{
118                 {"", "", errNonCanonicalName},
119                 {".", ".", nil},
120                 {"google..com", "", errNonCanonicalName},
121                 {"google.com", "", errNonCanonicalName},
122                 {"google..com.", "", errZeroSegLen},
123                 {"google.com.", "google.com.", nil},
124                 {".google.com.", "", errZeroSegLen},
125                 {"www..google.com.", "", errZeroSegLen},
126                 {"www.google.com.", "www.google.com.", nil},
127         }
128
129         for _, test := range tests {
130                 in := mustNewName(test.in)
131                 want := mustNewName(test.want)
132                 buf, err := in.pack(make([]byte, 0, 30), map[string]int{})
133                 if err != test.err {
134                         t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err)
135                         continue
136                 }
137                 if test.err != nil {
138                         continue
139                 }
140                 var got Name
141                 n, err := got.unpack(buf, 0)
142                 if err != nil {
143                         t.Errorf("Unpacking for %q failed: %v", test.in, err)
144                         continue
145                 }
146                 if n != len(buf) {
147                         t.Errorf(
148                                 "Unpacked different amount than packed for %q: got n = %d, want = %d",
149                                 test.in,
150                                 n,
151                                 len(buf),
152                         )
153                 }
154                 if got != want {
155                         t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want)
156                 }
157         }
158 }
159
160 func checkErrorPrefix(err error, prefix string) bool {
161         e, ok := err.(*nestedError)
162         return ok && e.s == prefix
163 }
164
165 func TestHeaderUnpackError(t *testing.T) {
166         wants := []string{
167                 "id",
168                 "bits",
169                 "questions",
170                 "answers",
171                 "authorities",
172                 "additionals",
173         }
174         var buf []byte
175         var h header
176         for _, want := range wants {
177                 n, err := h.unpack(buf, 0)
178                 if n != 0 || !checkErrorPrefix(err, want) {
179                         t.Errorf("got h.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want)
180                 }
181                 buf = append(buf, 0, 0)
182         }
183 }
184
185 func TestParserStart(t *testing.T) {
186         const want = "unpacking header"
187         var p Parser
188         for i := 0; i <= 1; i++ {
189                 _, err := p.Start([]byte{})
190                 if !checkErrorPrefix(err, want) {
191                         t.Errorf("got p.Start(nil) = _, %v, want = _, %s", err, want)
192                 }
193         }
194 }
195
196 func TestResourceNotStarted(t *testing.T) {
197         tests := []struct {
198                 name string
199                 fn   func(*Parser) error
200         }{
201                 {"CNAMEResource", func(p *Parser) error { _, err := p.CNAMEResource(); return err }},
202                 {"MXResource", func(p *Parser) error { _, err := p.MXResource(); return err }},
203                 {"NSResource", func(p *Parser) error { _, err := p.NSResource(); return err }},
204                 {"PTRResource", func(p *Parser) error { _, err := p.PTRResource(); return err }},
205                 {"SOAResource", func(p *Parser) error { _, err := p.SOAResource(); return err }},
206                 {"TXTResource", func(p *Parser) error { _, err := p.TXTResource(); return err }},
207                 {"SRVResource", func(p *Parser) error { _, err := p.SRVResource(); return err }},
208                 {"AResource", func(p *Parser) error { _, err := p.AResource(); return err }},
209                 {"AAAAResource", func(p *Parser) error { _, err := p.AAAAResource(); return err }},
210         }
211
212         for _, test := range tests {
213                 if err := test.fn(&Parser{}); err != ErrNotStarted {
214                         t.Errorf("got _, %v = p.%s(), want = _, %v", err, test.name, ErrNotStarted)
215                 }
216         }
217 }
218
219 func TestDNSPackUnpack(t *testing.T) {
220         wants := []Message{
221                 {
222                         Questions: []Question{
223                                 {
224                                         Name:  mustNewName("."),
225                                         Type:  TypeAAAA,
226                                         Class: ClassINET,
227                                 },
228                         },
229                         Answers:     []Resource{},
230                         Authorities: []Resource{},
231                         Additionals: []Resource{},
232                 },
233                 largeTestMsg(),
234         }
235         for i, want := range wants {
236                 b, err := want.Pack()
237                 if err != nil {
238                         t.Fatalf("%d: packing failed: %v", i, err)
239                 }
240                 var got Message
241                 err = got.Unpack(b)
242                 if err != nil {
243                         t.Fatalf("%d: unpacking failed: %v", i, err)
244                 }
245                 if !reflect.DeepEqual(got, want) {
246                         t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
247                 }
248         }
249 }
250
251 func TestSkipAll(t *testing.T) {
252         msg := largeTestMsg()
253         buf, err := msg.Pack()
254         if err != nil {
255                 t.Fatal("Packing large test message:", err)
256         }
257         var p Parser
258         if _, err := p.Start(buf); err != nil {
259                 t.Fatal(err)
260         }
261
262         tests := []struct {
263                 name string
264                 f    func() error
265         }{
266                 {"SkipAllQuestions", p.SkipAllQuestions},
267                 {"SkipAllAnswers", p.SkipAllAnswers},
268                 {"SkipAllAuthorities", p.SkipAllAuthorities},
269                 {"SkipAllAdditionals", p.SkipAllAdditionals},
270         }
271         for _, test := range tests {
272                 for i := 1; i <= 3; i++ {
273                         if err := test.f(); err != nil {
274                                 t.Errorf("Call #%d to %s(): %v", i, test.name, err)
275                         }
276                 }
277         }
278 }
279
280 func TestSkipEach(t *testing.T) {
281         msg := smallTestMsg()
282
283         buf, err := msg.Pack()
284         if err != nil {
285                 t.Fatal("Packing test message:", err)
286         }
287         var p Parser
288         if _, err := p.Start(buf); err != nil {
289                 t.Fatal(err)
290         }
291
292         tests := []struct {
293                 name string
294                 f    func() error
295         }{
296                 {"SkipQuestion", p.SkipQuestion},
297                 {"SkipAnswer", p.SkipAnswer},
298                 {"SkipAuthority", p.SkipAuthority},
299                 {"SkipAdditional", p.SkipAdditional},
300         }
301         for _, test := range tests {
302                 if err := test.f(); err != nil {
303                         t.Errorf("First call: got %s() = %v, want = %v", test.name, err, nil)
304                 }
305                 if err := test.f(); err != ErrSectionDone {
306                         t.Errorf("Second call: got %s() = %v, want = %v", test.name, err, ErrSectionDone)
307                 }
308         }
309 }
310
311 func TestSkipAfterRead(t *testing.T) {
312         msg := smallTestMsg()
313
314         buf, err := msg.Pack()
315         if err != nil {
316                 t.Fatal("Packing test message:", err)
317         }
318         var p Parser
319         if _, err := p.Start(buf); err != nil {
320                 t.Fatal(err)
321         }
322
323         tests := []struct {
324                 name string
325                 skip func() error
326                 read func() error
327         }{
328                 {"Question", p.SkipQuestion, func() error { _, err := p.Question(); return err }},
329                 {"Answer", p.SkipAnswer, func() error { _, err := p.Answer(); return err }},
330                 {"Authority", p.SkipAuthority, func() error { _, err := p.Authority(); return err }},
331                 {"Additional", p.SkipAdditional, func() error { _, err := p.Additional(); return err }},
332         }
333         for _, test := range tests {
334                 if err := test.read(); err != nil {
335                         t.Errorf("Got %s() = _, %v, want = _, %v", test.name, err, nil)
336                 }
337                 if err := test.skip(); err != ErrSectionDone {
338                         t.Errorf("Got Skip%s() = %v, want = %v", test.name, err, ErrSectionDone)
339                 }
340         }
341 }
342
343 func TestSkipNotStarted(t *testing.T) {
344         var p Parser
345
346         tests := []struct {
347                 name string
348                 f    func() error
349         }{
350                 {"SkipAllQuestions", p.SkipAllQuestions},
351                 {"SkipAllAnswers", p.SkipAllAnswers},
352                 {"SkipAllAuthorities", p.SkipAllAuthorities},
353                 {"SkipAllAdditionals", p.SkipAllAdditionals},
354         }
355         for _, test := range tests {
356                 if err := test.f(); err != ErrNotStarted {
357                         t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted)
358                 }
359         }
360 }
361
362 func TestTooManyRecords(t *testing.T) {
363         const recs = int(^uint16(0)) + 1
364         tests := []struct {
365                 name string
366                 msg  Message
367                 want error
368         }{
369                 {
370                         "Questions",
371                         Message{
372                                 Questions: make([]Question, recs),
373                         },
374                         errTooManyQuestions,
375                 },
376                 {
377                         "Answers",
378                         Message{
379                                 Answers: make([]Resource, recs),
380                         },
381                         errTooManyAnswers,
382                 },
383                 {
384                         "Authorities",
385                         Message{
386                                 Authorities: make([]Resource, recs),
387                         },
388                         errTooManyAuthorities,
389                 },
390                 {
391                         "Additionals",
392                         Message{
393                                 Additionals: make([]Resource, recs),
394                         },
395                         errTooManyAdditionals,
396                 },
397         }
398
399         for _, test := range tests {
400                 if _, got := test.msg.Pack(); got != test.want {
401                         t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want)
402                 }
403         }
404 }
405
406 func TestVeryLongTxt(t *testing.T) {
407         want := Resource{
408                 ResourceHeader{
409                         Name:  mustNewName("foo.bar.example.com."),
410                         Type:  TypeTXT,
411                         Class: ClassINET,
412                 },
413                 &TXTResource{loremIpsum},
414         }
415         buf, err := want.pack(make([]byte, 0, 8000), map[string]int{})
416         if err != nil {
417                 t.Fatal("Packing failed:", err)
418         }
419         var got Resource
420         off, err := got.Header.unpack(buf, 0)
421         if err != nil {
422                 t.Fatal("Unpacking ResourceHeader failed:", err)
423         }
424         body, n, err := unpackResourceBody(buf, off, got.Header)
425         if err != nil {
426                 t.Fatal("Unpacking failed:", err)
427         }
428         got.Body = body
429         if n != len(buf) {
430                 t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
431         }
432         if !reflect.DeepEqual(got, want) {
433                 t.Errorf("Got = %#v, want = %#v", got, want)
434         }
435 }
436
437 func TestStartError(t *testing.T) {
438         tests := []struct {
439                 name string
440                 fn   func(*Builder) error
441         }{
442                 {"Questions", func(b *Builder) error { return b.StartQuestions() }},
443                 {"Answers", func(b *Builder) error { return b.StartAnswers() }},
444                 {"Authorities", func(b *Builder) error { return b.StartAuthorities() }},
445                 {"Additionals", func(b *Builder) error { return b.StartAdditionals() }},
446         }
447
448         envs := []struct {
449                 name string
450                 fn   func() *Builder
451                 want error
452         }{
453                 {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
454                 {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
455         }
456
457         for _, env := range envs {
458                 for _, test := range tests {
459                         if got := test.fn(env.fn()); got != env.want {
460                                 t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want)
461                         }
462                 }
463         }
464 }
465
466 func TestBuilderResourceError(t *testing.T) {
467         tests := []struct {
468                 name string
469                 fn   func(*Builder) error
470         }{
471                 {"CNAMEResource", func(b *Builder) error { return b.CNAMEResource(ResourceHeader{}, CNAMEResource{}) }},
472                 {"MXResource", func(b *Builder) error { return b.MXResource(ResourceHeader{}, MXResource{}) }},
473                 {"NSResource", func(b *Builder) error { return b.NSResource(ResourceHeader{}, NSResource{}) }},
474                 {"PTRResource", func(b *Builder) error { return b.PTRResource(ResourceHeader{}, PTRResource{}) }},
475                 {"SOAResource", func(b *Builder) error { return b.SOAResource(ResourceHeader{}, SOAResource{}) }},
476                 {"TXTResource", func(b *Builder) error { return b.TXTResource(ResourceHeader{}, TXTResource{}) }},
477                 {"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }},
478                 {"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }},
479                 {"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }},
480         }
481
482         envs := []struct {
483                 name string
484                 fn   func() *Builder
485                 want error
486         }{
487                 {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
488                 {"sectionHeader", func() *Builder { return &Builder{section: sectionHeader} }, ErrNotStarted},
489                 {"sectionQuestions", func() *Builder { return &Builder{section: sectionQuestions} }, ErrNotStarted},
490                 {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
491         }
492
493         for _, env := range envs {
494                 for _, test := range tests {
495                         if got := test.fn(env.fn()); got != env.want {
496                                 t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want)
497                         }
498                 }
499         }
500 }
501
502 func TestFinishError(t *testing.T) {
503         var b Builder
504         want := ErrNotStarted
505         if _, got := b.Finish(); got != want {
506                 t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want)
507         }
508 }
509
510 func TestBuilder(t *testing.T) {
511         msg := largeTestMsg()
512         want, err := msg.Pack()
513         if err != nil {
514                 t.Fatal("Packing without builder:", err)
515         }
516
517         var b Builder
518         b.Start(nil, msg.Header)
519
520         if err := b.StartQuestions(); err != nil {
521                 t.Fatal("b.StartQuestions():", err)
522         }
523         for _, q := range msg.Questions {
524                 if err := b.Question(q); err != nil {
525                         t.Fatalf("b.Question(%#v): %v", q, err)
526                 }
527         }
528
529         if err := b.StartAnswers(); err != nil {
530                 t.Fatal("b.StartAnswers():", err)
531         }
532         for _, a := range msg.Answers {
533                 switch a.Header.Type {
534                 case TypeA:
535                         if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil {
536                                 t.Fatalf("b.AResource(%#v): %v", a, err)
537                         }
538                 case TypeNS:
539                         if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
540                                 t.Fatalf("b.NSResource(%#v): %v", a, err)
541                         }
542                 case TypeCNAME:
543                         if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil {
544                                 t.Fatalf("b.CNAMEResource(%#v): %v", a, err)
545                         }
546                 case TypeSOA:
547                         if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil {
548                                 t.Fatalf("b.SOAResource(%#v): %v", a, err)
549                         }
550                 case TypePTR:
551                         if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil {
552                                 t.Fatalf("b.PTRResource(%#v): %v", a, err)
553                         }
554                 case TypeMX:
555                         if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil {
556                                 t.Fatalf("b.MXResource(%#v): %v", a, err)
557                         }
558                 case TypeTXT:
559                         if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
560                                 t.Fatalf("b.TXTResource(%#v): %v", a, err)
561                         }
562                 case TypeAAAA:
563                         if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil {
564                                 t.Fatalf("b.AAAAResource(%#v): %v", a, err)
565                         }
566                 case TypeSRV:
567                         if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil {
568                                 t.Fatalf("b.SRVResource(%#v): %v", a, err)
569                         }
570                 }
571         }
572
573         if err := b.StartAuthorities(); err != nil {
574                 t.Fatal("b.StartAuthorities():", err)
575         }
576         for _, a := range msg.Authorities {
577                 if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
578                         t.Fatalf("b.NSResource(%#v): %v", a, err)
579                 }
580         }
581
582         if err := b.StartAdditionals(); err != nil {
583                 t.Fatal("b.StartAdditionals():", err)
584         }
585         for _, a := range msg.Additionals {
586                 if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
587                         t.Fatalf("b.TXTResource(%#v): %v", a, err)
588                 }
589         }
590
591         got, err := b.Finish()
592         if err != nil {
593                 t.Fatal("b.Finish():", err)
594         }
595         if !bytes.Equal(got, want) {
596                 t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want)
597         }
598 }
599
600 func TestResourcePack(t *testing.T) {
601         for _, tt := range []struct {
602                 m   Message
603                 err error
604         }{
605                 {
606                         Message{
607                                 Questions: []Question{
608                                         {
609                                                 Name:  mustNewName("."),
610                                                 Type:  TypeAAAA,
611                                                 Class: ClassINET,
612                                         },
613                                 },
614                                 Answers: []Resource{{ResourceHeader{}, nil}},
615                         },
616                         &nestedError{"packing Answer", errNilResouceBody},
617                 },
618                 {
619                         Message{
620                                 Questions: []Question{
621                                         {
622                                                 Name:  mustNewName("."),
623                                                 Type:  TypeAAAA,
624                                                 Class: ClassINET,
625                                         },
626                                 },
627                                 Authorities: []Resource{{ResourceHeader{}, (*NSResource)(nil)}},
628                         },
629                         &nestedError{"packing Authority",
630                                 &nestedError{"ResourceHeader",
631                                         &nestedError{"Name", errNonCanonicalName},
632                                 },
633                         },
634                 },
635                 {
636                         Message{
637                                 Questions: []Question{
638                                         {
639                                                 Name:  mustNewName("."),
640                                                 Type:  TypeA,
641                                                 Class: ClassINET,
642                                         },
643                                 },
644                                 Additionals: []Resource{{ResourceHeader{}, nil}},
645                         },
646                         &nestedError{"packing Additional", errNilResouceBody},
647                 },
648         } {
649                 _, err := tt.m.Pack()
650                 if !reflect.DeepEqual(err, tt.err) {
651                         t.Errorf("got %v for %v; want %v", err, tt.m, tt.err)
652                 }
653         }
654 }
655
656 func BenchmarkParsing(b *testing.B) {
657         b.ReportAllocs()
658
659         name := mustNewName("foo.bar.example.com.")
660         msg := Message{
661                 Header: Header{Response: true, Authoritative: true},
662                 Questions: []Question{
663                         {
664                                 Name:  name,
665                                 Type:  TypeA,
666                                 Class: ClassINET,
667                         },
668                 },
669                 Answers: []Resource{
670                         {
671                                 ResourceHeader{
672                                         Name:  name,
673                                         Class: ClassINET,
674                                 },
675                                 &AResource{[4]byte{}},
676                         },
677                         {
678                                 ResourceHeader{
679                                         Name:  name,
680                                         Class: ClassINET,
681                                 },
682                                 &AAAAResource{[16]byte{}},
683                         },
684                         {
685                                 ResourceHeader{
686                                         Name:  name,
687                                         Class: ClassINET,
688                                 },
689                                 &CNAMEResource{name},
690                         },
691                         {
692                                 ResourceHeader{
693                                         Name:  name,
694                                         Class: ClassINET,
695                                 },
696                                 &NSResource{name},
697                         },
698                 },
699         }
700
701         buf, err := msg.Pack()
702         if err != nil {
703                 b.Fatal("msg.Pack():", err)
704         }
705
706         for i := 0; i < b.N; i++ {
707                 var p Parser
708                 if _, err := p.Start(buf); err != nil {
709                         b.Fatal("p.Start(buf):", err)
710                 }
711
712                 for {
713                         _, err := p.Question()
714                         if err == ErrSectionDone {
715                                 break
716                         }
717                         if err != nil {
718                                 b.Fatal("p.Question():", err)
719                         }
720                 }
721
722                 for {
723                         h, err := p.AnswerHeader()
724                         if err == ErrSectionDone {
725                                 break
726                         }
727                         if err != nil {
728                                 panic(err)
729                         }
730
731                         switch h.Type {
732                         case TypeA:
733                                 if _, err := p.AResource(); err != nil {
734                                         b.Fatal("p.AResource():", err)
735                                 }
736                         case TypeAAAA:
737                                 if _, err := p.AAAAResource(); err != nil {
738                                         b.Fatal("p.AAAAResource():", err)
739                                 }
740                         case TypeCNAME:
741                                 if _, err := p.CNAMEResource(); err != nil {
742                                         b.Fatal("p.CNAMEResource():", err)
743                                 }
744                         case TypeNS:
745                                 if _, err := p.NSResource(); err != nil {
746                                         b.Fatal("p.NSResource():", err)
747                                 }
748                         default:
749                                 b.Fatalf("unknown type: %T", h)
750                         }
751                 }
752         }
753 }
754
755 func BenchmarkBuilding(b *testing.B) {
756         b.ReportAllocs()
757
758         name := mustNewName("foo.bar.example.com.")
759         buf := make([]byte, 0, packStartingCap)
760
761         for i := 0; i < b.N; i++ {
762                 var bld Builder
763                 bld.StartWithoutCompression(buf, Header{Response: true, Authoritative: true})
764
765                 if err := bld.StartQuestions(); err != nil {
766                         b.Fatal("bld.StartQuestions():", err)
767                 }
768                 q := Question{
769                         Name:  name,
770                         Type:  TypeA,
771                         Class: ClassINET,
772                 }
773                 if err := bld.Question(q); err != nil {
774                         b.Fatalf("bld.Question(%+v): %v", q, err)
775                 }
776
777                 hdr := ResourceHeader{
778                         Name:  name,
779                         Class: ClassINET,
780                 }
781                 if err := bld.StartAnswers(); err != nil {
782                         b.Fatal("bld.StartQuestions():", err)
783                 }
784
785                 ar := AResource{[4]byte{}}
786                 if err := bld.AResource(hdr, ar); err != nil {
787                         b.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err)
788                 }
789
790                 aaar := AAAAResource{[16]byte{}}
791                 if err := bld.AAAAResource(hdr, aaar); err != nil {
792                         b.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err)
793                 }
794
795                 cnr := CNAMEResource{name}
796                 if err := bld.CNAMEResource(hdr, cnr); err != nil {
797                         b.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err)
798                 }
799
800                 nsr := NSResource{name}
801                 if err := bld.NSResource(hdr, nsr); err != nil {
802                         b.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err)
803                 }
804
805                 if _, err := bld.Finish(); err != nil {
806                         b.Fatal("bld.Finish():", err)
807                 }
808         }
809 }
810
811 func smallTestMsg() Message {
812         name := mustNewName("example.com.")
813         return Message{
814                 Header: Header{Response: true, Authoritative: true},
815                 Questions: []Question{
816                         {
817                                 Name:  name,
818                                 Type:  TypeA,
819                                 Class: ClassINET,
820                         },
821                 },
822                 Answers: []Resource{
823                         {
824                                 ResourceHeader{
825                                         Name:  name,
826                                         Type:  TypeA,
827                                         Class: ClassINET,
828                                 },
829                                 &AResource{[4]byte{127, 0, 0, 1}},
830                         },
831                 },
832                 Authorities: []Resource{
833                         {
834                                 ResourceHeader{
835                                         Name:  name,
836                                         Type:  TypeA,
837                                         Class: ClassINET,
838                                 },
839                                 &AResource{[4]byte{127, 0, 0, 1}},
840                         },
841                 },
842                 Additionals: []Resource{
843                         {
844                                 ResourceHeader{
845                                         Name:  name,
846                                         Type:  TypeA,
847                                         Class: ClassINET,
848                                 },
849                                 &AResource{[4]byte{127, 0, 0, 1}},
850                         },
851                 },
852         }
853 }
854
855 func largeTestMsg() Message {
856         name := mustNewName("foo.bar.example.com.")
857         return Message{
858                 Header: Header{Response: true, Authoritative: true},
859                 Questions: []Question{
860                         {
861                                 Name:  name,
862                                 Type:  TypeA,
863                                 Class: ClassINET,
864                         },
865                 },
866                 Answers: []Resource{
867                         {
868                                 ResourceHeader{
869                                         Name:  name,
870                                         Type:  TypeA,
871                                         Class: ClassINET,
872                                 },
873                                 &AResource{[4]byte{127, 0, 0, 1}},
874                         },
875                         {
876                                 ResourceHeader{
877                                         Name:  name,
878                                         Type:  TypeA,
879                                         Class: ClassINET,
880                                 },
881                                 &AResource{[4]byte{127, 0, 0, 2}},
882                         },
883                         {
884                                 ResourceHeader{
885                                         Name:  name,
886                                         Type:  TypeAAAA,
887                                         Class: ClassINET,
888                                 },
889                                 &AAAAResource{[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
890                         },
891                         {
892                                 ResourceHeader{
893                                         Name:  name,
894                                         Type:  TypeCNAME,
895                                         Class: ClassINET,
896                                 },
897                                 &CNAMEResource{mustNewName("alias.example.com.")},
898                         },
899                         {
900                                 ResourceHeader{
901                                         Name:  name,
902                                         Type:  TypeSOA,
903                                         Class: ClassINET,
904                                 },
905                                 &SOAResource{
906                                         NS:      mustNewName("ns1.example.com."),
907                                         MBox:    mustNewName("mb.example.com."),
908                                         Serial:  1,
909                                         Refresh: 2,
910                                         Retry:   3,
911                                         Expire:  4,
912                                         MinTTL:  5,
913                                 },
914                         },
915                         {
916                                 ResourceHeader{
917                                         Name:  name,
918                                         Type:  TypePTR,
919                                         Class: ClassINET,
920                                 },
921                                 &PTRResource{mustNewName("ptr.example.com.")},
922                         },
923                         {
924                                 ResourceHeader{
925                                         Name:  name,
926                                         Type:  TypeMX,
927                                         Class: ClassINET,
928                                 },
929                                 &MXResource{
930                                         7,
931                                         mustNewName("mx.example.com."),
932                                 },
933                         },
934                         {
935                                 ResourceHeader{
936                                         Name:  name,
937                                         Type:  TypeSRV,
938                                         Class: ClassINET,
939                                 },
940                                 &SRVResource{
941                                         8,
942                                         9,
943                                         11,
944                                         mustNewName("srv.example.com."),
945                                 },
946                         },
947                 },
948                 Authorities: []Resource{
949                         {
950                                 ResourceHeader{
951                                         Name:  name,
952                                         Type:  TypeNS,
953                                         Class: ClassINET,
954                                 },
955                                 &NSResource{mustNewName("ns1.example.com.")},
956                         },
957                         {
958                                 ResourceHeader{
959                                         Name:  name,
960                                         Type:  TypeNS,
961                                         Class: ClassINET,
962                                 },
963                                 &NSResource{mustNewName("ns2.example.com.")},
964                         },
965                 },
966                 Additionals: []Resource{
967                         {
968                                 ResourceHeader{
969                                         Name:  name,
970                                         Type:  TypeTXT,
971                                         Class: ClassINET,
972                                 },
973                                 &TXTResource{"So Long, and Thanks for All the Fish"},
974                         },
975                         {
976                                 ResourceHeader{
977                                         Name:  name,
978                                         Type:  TypeTXT,
979                                         Class: ClassINET,
980                                 },
981                                 &TXTResource{"Hamster Huey and the Gooey Kablooie"},
982                         },
983                 },
984         }
985 }
986
987 const loremIpsum = `
988 Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro
989 nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos,
990 magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas
991 regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei
992 nam ipsum assentior.
993
994 Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum
995 facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque
996 no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem
997 reformidans et. Qui ei eros porro reformidans, ius suas veritus
998 torquatos ex. Mea te facer alterum consequat.
999
1000 Soleat torquatos democritum sed et, no mea congue appareat, facer
1001 aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet
1002 phaedrum ad nam. Ea detracto verterem liberavisse has, delectus
1003 suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis
1004 honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum
1005 mollis.
1006
1007 Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad
1008 vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque
1009 vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum
1010 dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut
1011 pro, vel ne saepe senserit consetetur.
1012
1013 Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no
1014 enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum
1015 sententiae deterruisset ut. At suas timeam euismod cum, offendit
1016 appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam
1017 accusata intellegebat, noluisse instructior sea id. Nec te nonumes
1018 habemus appellantur, quis dignissim vituperata eu nam.
1019
1020 At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet
1021 iisque an mea. Per eu dicant ponderum accommodare. Pri alienum
1022 placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea
1023 eligendi disputationi. Ius no tation everti impedit, ei magna quidam
1024 mediocritatem pri.
1025
1026 Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam,
1027 ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo
1028 has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut
1029 iudico albucius his.
1030
1031 Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue
1032 dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse,
1033 an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At
1034 vis dicant abhorreant, utinam forensibus nec ne, mei te docendi
1035 consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae
1036 usu, dicit graeco disputando id has.
1037
1038 Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec
1039 torquatos sadipscing ei, ancillae molestie per in. Malis principes duo
1040 ea, usu liber postulant ei.
1041
1042 Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta
1043 feugiat duo. Congue option meliore ex qui, noster invenire appellantur
1044 ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an
1045 probo minimum, et nam illud falli tempor.
1046
1047 Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens
1048 tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat
1049 tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri.
1050
1051 Ad oratio blandit aliquando pro. Vis et dolorum rationibus
1052 philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et,
1053 ne qui nisl verear saperet, vel te quaestio forensibus. Per odio
1054 option delenit an. Alii placerat has no, in pri nihil platonem
1055 cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea
1056 an.
1057
1058 Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat
1059 accusam mea et. Elitr labitur albucius et pri, an labore feugait mel.
1060 Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no
1061 error volumus scripserit. In pro paulo iudico, quo ei dolorem
1062 verterem, affert fabellas dissentiet ea vix.
1063
1064 Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi
1065 salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at
1066 nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit
1067 utroque vis, ex equidem detraxit temporibus has.
1068
1069 Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas
1070 pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad
1071 mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata
1072 interesset. Mel sapientem prodesset abhorreant et, oblique suscipit
1073 eam id.
1074
1075 An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens
1076 inciderint no sea. Ea persius maluisset vix, ne vim appellantur
1077 instructior, consul quidam definiebas pri id. Cum integre feugiat
1078 pericula in, ex sed persius similique, mel ne natum dicit percipitur.
1079
1080 Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore
1081 neglegentur, mei tincidunt percipitur ei. Pro ad simul integre
1082 rationibus. Eu vel alii honestatis definitiones, mea no nonumy
1083 reprehendunt.
1084
1085 Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix
1086 adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat
1087 duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum
1088 debitis nostrum no, ut vel aliquid vivendo.
1089
1090 Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi.
1091 Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo
1092 dolore impedit id eam, et aeque feugait assentior has. Quando sensibus
1093 nec ex. Possit sensibus pri ad, unum mutat periculis cu vix.
1094
1095 Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit
1096 sonet tempor. No per solet aeterno deseruisse. Petentium salutandi
1097 definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi
1098 vis, modus offendit omittantur te mel.
1099
1100 Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam
1101 melius conceptam est ne, quo in minimum apeirian delicata, ut ius
1102 porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu
1103 his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te
1104 per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis
1105 ad idque fabellas intellegebat.
1106
1107 Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut,
1108 mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne
1109 alia corpora invenire, alia prima soleat te cum. Eleifend posidonium
1110 nam at.
1111
1112 Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril
1113 discere. Nec civibus officiis dissentiunt ex, est te liber ludus
1114 elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit
1115 comprehensam, nam te inermis delectus, saepe inermis senserit.
1116 `