message_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  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. package dnsmessage
  5. import (
  6. "bytes"
  7. "fmt"
  8. "reflect"
  9. "strings"
  10. "testing"
  11. )
  12. func mustNewName(name string) Name {
  13. n, err := NewName(name)
  14. if err != nil {
  15. panic(err)
  16. }
  17. return n
  18. }
  19. func (m *Message) String() string {
  20. s := fmt.Sprintf("Message: %#v\n", &m.Header)
  21. if len(m.Questions) > 0 {
  22. s += "-- Questions\n"
  23. for _, q := range m.Questions {
  24. s += fmt.Sprintf("%#v\n", q)
  25. }
  26. }
  27. if len(m.Answers) > 0 {
  28. s += "-- Answers\n"
  29. for _, a := range m.Answers {
  30. s += fmt.Sprintf("%#v\n", a)
  31. }
  32. }
  33. if len(m.Authorities) > 0 {
  34. s += "-- Authorities\n"
  35. for _, ns := range m.Authorities {
  36. s += fmt.Sprintf("%#v\n", ns)
  37. }
  38. }
  39. if len(m.Additionals) > 0 {
  40. s += "-- Additionals\n"
  41. for _, e := range m.Additionals {
  42. s += fmt.Sprintf("%#v\n", e)
  43. }
  44. }
  45. return s
  46. }
  47. func TestNameString(t *testing.T) {
  48. want := "foo"
  49. name := mustNewName(want)
  50. if got := fmt.Sprint(name); got != want {
  51. t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want)
  52. }
  53. }
  54. func TestQuestionPackUnpack(t *testing.T) {
  55. want := Question{
  56. Name: mustNewName("."),
  57. Type: TypeA,
  58. Class: ClassINET,
  59. }
  60. buf, err := want.pack(make([]byte, 1, 50), map[string]int{}, 1)
  61. if err != nil {
  62. t.Fatal("Packing failed:", err)
  63. }
  64. var p Parser
  65. p.msg = buf
  66. p.header.questions = 1
  67. p.section = sectionQuestions
  68. p.off = 1
  69. got, err := p.Question()
  70. if err != nil {
  71. t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:]))
  72. }
  73. if p.off != len(buf) {
  74. t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf))
  75. }
  76. if !reflect.DeepEqual(got, want) {
  77. t.Errorf("Got = %+v, want = %+v", got, want)
  78. }
  79. }
  80. func TestName(t *testing.T) {
  81. tests := []string{
  82. "",
  83. ".",
  84. "google..com",
  85. "google.com",
  86. "google..com.",
  87. "google.com.",
  88. ".google.com.",
  89. "www..google.com.",
  90. "www.google.com.",
  91. }
  92. for _, test := range tests {
  93. n, err := NewName(test)
  94. if err != nil {
  95. t.Errorf("Creating name for %q: %v", test, err)
  96. continue
  97. }
  98. if ns := n.String(); ns != test {
  99. t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test)
  100. continue
  101. }
  102. }
  103. }
  104. func TestNamePackUnpack(t *testing.T) {
  105. tests := []struct {
  106. in string
  107. want string
  108. err error
  109. }{
  110. {"", "", errNonCanonicalName},
  111. {".", ".", nil},
  112. {"google..com", "", errNonCanonicalName},
  113. {"google.com", "", errNonCanonicalName},
  114. {"google..com.", "", errZeroSegLen},
  115. {"google.com.", "google.com.", nil},
  116. {".google.com.", "", errZeroSegLen},
  117. {"www..google.com.", "", errZeroSegLen},
  118. {"www.google.com.", "www.google.com.", nil},
  119. }
  120. for _, test := range tests {
  121. in := mustNewName(test.in)
  122. want := mustNewName(test.want)
  123. buf, err := in.pack(make([]byte, 0, 30), map[string]int{}, 0)
  124. if err != test.err {
  125. t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err)
  126. continue
  127. }
  128. if test.err != nil {
  129. continue
  130. }
  131. var got Name
  132. n, err := got.unpack(buf, 0)
  133. if err != nil {
  134. t.Errorf("Unpacking for %q failed: %v", test.in, err)
  135. continue
  136. }
  137. if n != len(buf) {
  138. t.Errorf(
  139. "Unpacked different amount than packed for %q: got n = %d, want = %d",
  140. test.in,
  141. n,
  142. len(buf),
  143. )
  144. }
  145. if got != want {
  146. t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want)
  147. }
  148. }
  149. }
  150. func TestIncompressibleName(t *testing.T) {
  151. name := mustNewName("example.com.")
  152. compression := map[string]int{}
  153. buf, err := name.pack(make([]byte, 0, 100), compression, 0)
  154. if err != nil {
  155. t.Fatal("First packing failed:", err)
  156. }
  157. buf, err = name.pack(buf, compression, 0)
  158. if err != nil {
  159. t.Fatal("Second packing failed:", err)
  160. }
  161. var n1 Name
  162. off, err := n1.unpackCompressed(buf, 0, false /* allowCompression */)
  163. if err != nil {
  164. t.Fatal("Unpacking incompressible name without pointers failed:", err)
  165. }
  166. var n2 Name
  167. if _, err := n2.unpackCompressed(buf, off, false /* allowCompression */); err != errCompressedSRV {
  168. t.Errorf("Unpacking compressed incompressible name with pointers: got err = %v, want = %v", err, errCompressedSRV)
  169. }
  170. }
  171. func checkErrorPrefix(err error, prefix string) bool {
  172. e, ok := err.(*nestedError)
  173. return ok && e.s == prefix
  174. }
  175. func TestHeaderUnpackError(t *testing.T) {
  176. wants := []string{
  177. "id",
  178. "bits",
  179. "questions",
  180. "answers",
  181. "authorities",
  182. "additionals",
  183. }
  184. var buf []byte
  185. var h header
  186. for _, want := range wants {
  187. n, err := h.unpack(buf, 0)
  188. if n != 0 || !checkErrorPrefix(err, want) {
  189. t.Errorf("got h.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want)
  190. }
  191. buf = append(buf, 0, 0)
  192. }
  193. }
  194. func TestParserStart(t *testing.T) {
  195. const want = "unpacking header"
  196. var p Parser
  197. for i := 0; i <= 1; i++ {
  198. _, err := p.Start([]byte{})
  199. if !checkErrorPrefix(err, want) {
  200. t.Errorf("got p.Start(nil) = _, %v, want = _, %s", err, want)
  201. }
  202. }
  203. }
  204. func TestResourceNotStarted(t *testing.T) {
  205. tests := []struct {
  206. name string
  207. fn func(*Parser) error
  208. }{
  209. {"CNAMEResource", func(p *Parser) error { _, err := p.CNAMEResource(); return err }},
  210. {"MXResource", func(p *Parser) error { _, err := p.MXResource(); return err }},
  211. {"NSResource", func(p *Parser) error { _, err := p.NSResource(); return err }},
  212. {"PTRResource", func(p *Parser) error { _, err := p.PTRResource(); return err }},
  213. {"SOAResource", func(p *Parser) error { _, err := p.SOAResource(); return err }},
  214. {"TXTResource", func(p *Parser) error { _, err := p.TXTResource(); return err }},
  215. {"SRVResource", func(p *Parser) error { _, err := p.SRVResource(); return err }},
  216. {"AResource", func(p *Parser) error { _, err := p.AResource(); return err }},
  217. {"AAAAResource", func(p *Parser) error { _, err := p.AAAAResource(); return err }},
  218. }
  219. for _, test := range tests {
  220. if err := test.fn(&Parser{}); err != ErrNotStarted {
  221. t.Errorf("got _, %v = p.%s(), want = _, %v", err, test.name, ErrNotStarted)
  222. }
  223. }
  224. }
  225. func TestDNSPackUnpack(t *testing.T) {
  226. wants := []Message{
  227. {
  228. Questions: []Question{
  229. {
  230. Name: mustNewName("."),
  231. Type: TypeAAAA,
  232. Class: ClassINET,
  233. },
  234. },
  235. Answers: []Resource{},
  236. Authorities: []Resource{},
  237. Additionals: []Resource{},
  238. },
  239. largeTestMsg(),
  240. }
  241. for i, want := range wants {
  242. b, err := want.Pack()
  243. if err != nil {
  244. t.Fatalf("%d: packing failed: %v", i, err)
  245. }
  246. var got Message
  247. err = got.Unpack(b)
  248. if err != nil {
  249. t.Fatalf("%d: unpacking failed: %v", i, err)
  250. }
  251. if !reflect.DeepEqual(got, want) {
  252. t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
  253. }
  254. }
  255. }
  256. func TestDNSAppendPackUnpack(t *testing.T) {
  257. wants := []Message{
  258. {
  259. Questions: []Question{
  260. {
  261. Name: mustNewName("."),
  262. Type: TypeAAAA,
  263. Class: ClassINET,
  264. },
  265. },
  266. Answers: []Resource{},
  267. Authorities: []Resource{},
  268. Additionals: []Resource{},
  269. },
  270. largeTestMsg(),
  271. }
  272. for i, want := range wants {
  273. b := make([]byte, 2, 514)
  274. b, err := want.AppendPack(b)
  275. if err != nil {
  276. t.Fatalf("%d: packing failed: %v", i, err)
  277. }
  278. b = b[2:]
  279. var got Message
  280. err = got.Unpack(b)
  281. if err != nil {
  282. t.Fatalf("%d: unpacking failed: %v", i, err)
  283. }
  284. if !reflect.DeepEqual(got, want) {
  285. t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
  286. }
  287. }
  288. }
  289. func TestSkipAll(t *testing.T) {
  290. msg := largeTestMsg()
  291. buf, err := msg.Pack()
  292. if err != nil {
  293. t.Fatal("Packing large test message:", err)
  294. }
  295. var p Parser
  296. if _, err := p.Start(buf); err != nil {
  297. t.Fatal(err)
  298. }
  299. tests := []struct {
  300. name string
  301. f func() error
  302. }{
  303. {"SkipAllQuestions", p.SkipAllQuestions},
  304. {"SkipAllAnswers", p.SkipAllAnswers},
  305. {"SkipAllAuthorities", p.SkipAllAuthorities},
  306. {"SkipAllAdditionals", p.SkipAllAdditionals},
  307. }
  308. for _, test := range tests {
  309. for i := 1; i <= 3; i++ {
  310. if err := test.f(); err != nil {
  311. t.Errorf("Call #%d to %s(): %v", i, test.name, err)
  312. }
  313. }
  314. }
  315. }
  316. func TestSkipEach(t *testing.T) {
  317. msg := smallTestMsg()
  318. buf, err := msg.Pack()
  319. if err != nil {
  320. t.Fatal("Packing test message:", err)
  321. }
  322. var p Parser
  323. if _, err := p.Start(buf); err != nil {
  324. t.Fatal(err)
  325. }
  326. tests := []struct {
  327. name string
  328. f func() error
  329. }{
  330. {"SkipQuestion", p.SkipQuestion},
  331. {"SkipAnswer", p.SkipAnswer},
  332. {"SkipAuthority", p.SkipAuthority},
  333. {"SkipAdditional", p.SkipAdditional},
  334. }
  335. for _, test := range tests {
  336. if err := test.f(); err != nil {
  337. t.Errorf("First call: got %s() = %v, want = %v", test.name, err, nil)
  338. }
  339. if err := test.f(); err != ErrSectionDone {
  340. t.Errorf("Second call: got %s() = %v, want = %v", test.name, err, ErrSectionDone)
  341. }
  342. }
  343. }
  344. func TestSkipAfterRead(t *testing.T) {
  345. msg := smallTestMsg()
  346. buf, err := msg.Pack()
  347. if err != nil {
  348. t.Fatal("Packing test message:", err)
  349. }
  350. var p Parser
  351. if _, err := p.Start(buf); err != nil {
  352. t.Fatal(err)
  353. }
  354. tests := []struct {
  355. name string
  356. skip func() error
  357. read func() error
  358. }{
  359. {"Question", p.SkipQuestion, func() error { _, err := p.Question(); return err }},
  360. {"Answer", p.SkipAnswer, func() error { _, err := p.Answer(); return err }},
  361. {"Authority", p.SkipAuthority, func() error { _, err := p.Authority(); return err }},
  362. {"Additional", p.SkipAdditional, func() error { _, err := p.Additional(); return err }},
  363. }
  364. for _, test := range tests {
  365. if err := test.read(); err != nil {
  366. t.Errorf("Got %s() = _, %v, want = _, %v", test.name, err, nil)
  367. }
  368. if err := test.skip(); err != ErrSectionDone {
  369. t.Errorf("Got Skip%s() = %v, want = %v", test.name, err, ErrSectionDone)
  370. }
  371. }
  372. }
  373. func TestSkipNotStarted(t *testing.T) {
  374. var p Parser
  375. tests := []struct {
  376. name string
  377. f func() error
  378. }{
  379. {"SkipAllQuestions", p.SkipAllQuestions},
  380. {"SkipAllAnswers", p.SkipAllAnswers},
  381. {"SkipAllAuthorities", p.SkipAllAuthorities},
  382. {"SkipAllAdditionals", p.SkipAllAdditionals},
  383. }
  384. for _, test := range tests {
  385. if err := test.f(); err != ErrNotStarted {
  386. t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted)
  387. }
  388. }
  389. }
  390. func TestTooManyRecords(t *testing.T) {
  391. const recs = int(^uint16(0)) + 1
  392. tests := []struct {
  393. name string
  394. msg Message
  395. want error
  396. }{
  397. {
  398. "Questions",
  399. Message{
  400. Questions: make([]Question, recs),
  401. },
  402. errTooManyQuestions,
  403. },
  404. {
  405. "Answers",
  406. Message{
  407. Answers: make([]Resource, recs),
  408. },
  409. errTooManyAnswers,
  410. },
  411. {
  412. "Authorities",
  413. Message{
  414. Authorities: make([]Resource, recs),
  415. },
  416. errTooManyAuthorities,
  417. },
  418. {
  419. "Additionals",
  420. Message{
  421. Additionals: make([]Resource, recs),
  422. },
  423. errTooManyAdditionals,
  424. },
  425. }
  426. for _, test := range tests {
  427. if _, got := test.msg.Pack(); got != test.want {
  428. t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want)
  429. }
  430. }
  431. }
  432. func TestVeryLongTxt(t *testing.T) {
  433. want := Resource{
  434. ResourceHeader{
  435. Name: mustNewName("foo.bar.example.com."),
  436. Type: TypeTXT,
  437. Class: ClassINET,
  438. },
  439. &TXTResource{[]string{
  440. "",
  441. "",
  442. "foo bar",
  443. "",
  444. "www.example.com",
  445. "www.example.com.",
  446. strings.Repeat(".", 255),
  447. }},
  448. }
  449. buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}, 0)
  450. if err != nil {
  451. t.Fatal("Packing failed:", err)
  452. }
  453. var got Resource
  454. off, err := got.Header.unpack(buf, 0)
  455. if err != nil {
  456. t.Fatal("Unpacking ResourceHeader failed:", err)
  457. }
  458. body, n, err := unpackResourceBody(buf, off, got.Header)
  459. if err != nil {
  460. t.Fatal("Unpacking failed:", err)
  461. }
  462. got.Body = body
  463. if n != len(buf) {
  464. t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
  465. }
  466. if !reflect.DeepEqual(got, want) {
  467. t.Errorf("Got = %#v, want = %#v", got, want)
  468. }
  469. }
  470. func TestTooLongTxt(t *testing.T) {
  471. rb := TXTResource{[]string{strings.Repeat(".", 256)}}
  472. if _, err := rb.pack(make([]byte, 0, 8000), map[string]int{}, 0); err != errStringTooLong {
  473. t.Errorf("Packing TXTRecord with 256 character string: got err = %v, want = %v", err, errStringTooLong)
  474. }
  475. }
  476. func TestStartAppends(t *testing.T) {
  477. buf := make([]byte, 2, 514)
  478. wantBuf := []byte{4, 44}
  479. copy(buf, wantBuf)
  480. b := NewBuilder(buf, Header{})
  481. b.EnableCompression()
  482. buf, err := b.Finish()
  483. if err != nil {
  484. t.Fatal("Building failed:", err)
  485. }
  486. if got, want := len(buf), headerLen+2; got != want {
  487. t.Errorf("Got len(buf} = %d, want = %d", got, want)
  488. }
  489. if string(buf[:2]) != string(wantBuf) {
  490. t.Errorf("Original data not preserved, got = %v, want = %v", buf[:2], wantBuf)
  491. }
  492. }
  493. func TestStartError(t *testing.T) {
  494. tests := []struct {
  495. name string
  496. fn func(*Builder) error
  497. }{
  498. {"Questions", func(b *Builder) error { return b.StartQuestions() }},
  499. {"Answers", func(b *Builder) error { return b.StartAnswers() }},
  500. {"Authorities", func(b *Builder) error { return b.StartAuthorities() }},
  501. {"Additionals", func(b *Builder) error { return b.StartAdditionals() }},
  502. }
  503. envs := []struct {
  504. name string
  505. fn func() *Builder
  506. want error
  507. }{
  508. {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
  509. {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
  510. }
  511. for _, env := range envs {
  512. for _, test := range tests {
  513. if got := test.fn(env.fn()); got != env.want {
  514. t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want)
  515. }
  516. }
  517. }
  518. }
  519. func TestBuilderResourceError(t *testing.T) {
  520. tests := []struct {
  521. name string
  522. fn func(*Builder) error
  523. }{
  524. {"CNAMEResource", func(b *Builder) error { return b.CNAMEResource(ResourceHeader{}, CNAMEResource{}) }},
  525. {"MXResource", func(b *Builder) error { return b.MXResource(ResourceHeader{}, MXResource{}) }},
  526. {"NSResource", func(b *Builder) error { return b.NSResource(ResourceHeader{}, NSResource{}) }},
  527. {"PTRResource", func(b *Builder) error { return b.PTRResource(ResourceHeader{}, PTRResource{}) }},
  528. {"SOAResource", func(b *Builder) error { return b.SOAResource(ResourceHeader{}, SOAResource{}) }},
  529. {"TXTResource", func(b *Builder) error { return b.TXTResource(ResourceHeader{}, TXTResource{}) }},
  530. {"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }},
  531. {"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }},
  532. {"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }},
  533. }
  534. envs := []struct {
  535. name string
  536. fn func() *Builder
  537. want error
  538. }{
  539. {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
  540. {"sectionHeader", func() *Builder { return &Builder{section: sectionHeader} }, ErrNotStarted},
  541. {"sectionQuestions", func() *Builder { return &Builder{section: sectionQuestions} }, ErrNotStarted},
  542. {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
  543. }
  544. for _, env := range envs {
  545. for _, test := range tests {
  546. if got := test.fn(env.fn()); got != env.want {
  547. t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want)
  548. }
  549. }
  550. }
  551. }
  552. func TestFinishError(t *testing.T) {
  553. var b Builder
  554. want := ErrNotStarted
  555. if _, got := b.Finish(); got != want {
  556. t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want)
  557. }
  558. }
  559. func TestBuilder(t *testing.T) {
  560. msg := largeTestMsg()
  561. want, err := msg.Pack()
  562. if err != nil {
  563. t.Fatal("Packing without builder:", err)
  564. }
  565. b := NewBuilder(nil, msg.Header)
  566. b.EnableCompression()
  567. if err := b.StartQuestions(); err != nil {
  568. t.Fatal("b.StartQuestions():", err)
  569. }
  570. for _, q := range msg.Questions {
  571. if err := b.Question(q); err != nil {
  572. t.Fatalf("b.Question(%#v): %v", q, err)
  573. }
  574. }
  575. if err := b.StartAnswers(); err != nil {
  576. t.Fatal("b.StartAnswers():", err)
  577. }
  578. for _, a := range msg.Answers {
  579. switch a.Header.Type {
  580. case TypeA:
  581. if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil {
  582. t.Fatalf("b.AResource(%#v): %v", a, err)
  583. }
  584. case TypeNS:
  585. if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
  586. t.Fatalf("b.NSResource(%#v): %v", a, err)
  587. }
  588. case TypeCNAME:
  589. if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil {
  590. t.Fatalf("b.CNAMEResource(%#v): %v", a, err)
  591. }
  592. case TypeSOA:
  593. if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil {
  594. t.Fatalf("b.SOAResource(%#v): %v", a, err)
  595. }
  596. case TypePTR:
  597. if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil {
  598. t.Fatalf("b.PTRResource(%#v): %v", a, err)
  599. }
  600. case TypeMX:
  601. if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil {
  602. t.Fatalf("b.MXResource(%#v): %v", a, err)
  603. }
  604. case TypeTXT:
  605. if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
  606. t.Fatalf("b.TXTResource(%#v): %v", a, err)
  607. }
  608. case TypeAAAA:
  609. if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil {
  610. t.Fatalf("b.AAAAResource(%#v): %v", a, err)
  611. }
  612. case TypeSRV:
  613. if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil {
  614. t.Fatalf("b.SRVResource(%#v): %v", a, err)
  615. }
  616. }
  617. }
  618. if err := b.StartAuthorities(); err != nil {
  619. t.Fatal("b.StartAuthorities():", err)
  620. }
  621. for _, a := range msg.Authorities {
  622. if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
  623. t.Fatalf("b.NSResource(%#v): %v", a, err)
  624. }
  625. }
  626. if err := b.StartAdditionals(); err != nil {
  627. t.Fatal("b.StartAdditionals():", err)
  628. }
  629. for _, a := range msg.Additionals {
  630. if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
  631. t.Fatalf("b.TXTResource(%#v): %v", a, err)
  632. }
  633. }
  634. got, err := b.Finish()
  635. if err != nil {
  636. t.Fatal("b.Finish():", err)
  637. }
  638. if !bytes.Equal(got, want) {
  639. t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want)
  640. }
  641. }
  642. func TestResourcePack(t *testing.T) {
  643. for _, tt := range []struct {
  644. m Message
  645. err error
  646. }{
  647. {
  648. Message{
  649. Questions: []Question{
  650. {
  651. Name: mustNewName("."),
  652. Type: TypeAAAA,
  653. Class: ClassINET,
  654. },
  655. },
  656. Answers: []Resource{{ResourceHeader{}, nil}},
  657. },
  658. &nestedError{"packing Answer", errNilResouceBody},
  659. },
  660. {
  661. Message{
  662. Questions: []Question{
  663. {
  664. Name: mustNewName("."),
  665. Type: TypeAAAA,
  666. Class: ClassINET,
  667. },
  668. },
  669. Authorities: []Resource{{ResourceHeader{}, (*NSResource)(nil)}},
  670. },
  671. &nestedError{"packing Authority",
  672. &nestedError{"ResourceHeader",
  673. &nestedError{"Name", errNonCanonicalName},
  674. },
  675. },
  676. },
  677. {
  678. Message{
  679. Questions: []Question{
  680. {
  681. Name: mustNewName("."),
  682. Type: TypeA,
  683. Class: ClassINET,
  684. },
  685. },
  686. Additionals: []Resource{{ResourceHeader{}, nil}},
  687. },
  688. &nestedError{"packing Additional", errNilResouceBody},
  689. },
  690. } {
  691. _, err := tt.m.Pack()
  692. if !reflect.DeepEqual(err, tt.err) {
  693. t.Errorf("got %v for %v; want %v", err, tt.m, tt.err)
  694. }
  695. }
  696. }
  697. func benchmarkParsingSetup() ([]byte, error) {
  698. name := mustNewName("foo.bar.example.com.")
  699. msg := Message{
  700. Header: Header{Response: true, Authoritative: true},
  701. Questions: []Question{
  702. {
  703. Name: name,
  704. Type: TypeA,
  705. Class: ClassINET,
  706. },
  707. },
  708. Answers: []Resource{
  709. {
  710. ResourceHeader{
  711. Name: name,
  712. Class: ClassINET,
  713. },
  714. &AResource{[4]byte{}},
  715. },
  716. {
  717. ResourceHeader{
  718. Name: name,
  719. Class: ClassINET,
  720. },
  721. &AAAAResource{[16]byte{}},
  722. },
  723. {
  724. ResourceHeader{
  725. Name: name,
  726. Class: ClassINET,
  727. },
  728. &CNAMEResource{name},
  729. },
  730. {
  731. ResourceHeader{
  732. Name: name,
  733. Class: ClassINET,
  734. },
  735. &NSResource{name},
  736. },
  737. },
  738. }
  739. buf, err := msg.Pack()
  740. if err != nil {
  741. return nil, fmt.Errorf("msg.Pack(): %v", err)
  742. }
  743. return buf, nil
  744. }
  745. func benchmarkParsing(tb testing.TB, buf []byte) {
  746. var p Parser
  747. if _, err := p.Start(buf); err != nil {
  748. tb.Fatal("p.Start(buf):", err)
  749. }
  750. for {
  751. _, err := p.Question()
  752. if err == ErrSectionDone {
  753. break
  754. }
  755. if err != nil {
  756. tb.Fatal("p.Question():", err)
  757. }
  758. }
  759. for {
  760. h, err := p.AnswerHeader()
  761. if err == ErrSectionDone {
  762. break
  763. }
  764. if err != nil {
  765. panic(err)
  766. }
  767. switch h.Type {
  768. case TypeA:
  769. if _, err := p.AResource(); err != nil {
  770. tb.Fatal("p.AResource():", err)
  771. }
  772. case TypeAAAA:
  773. if _, err := p.AAAAResource(); err != nil {
  774. tb.Fatal("p.AAAAResource():", err)
  775. }
  776. case TypeCNAME:
  777. if _, err := p.CNAMEResource(); err != nil {
  778. tb.Fatal("p.CNAMEResource():", err)
  779. }
  780. case TypeNS:
  781. if _, err := p.NSResource(); err != nil {
  782. tb.Fatal("p.NSResource():", err)
  783. }
  784. default:
  785. tb.Fatalf("unknown type: %T", h)
  786. }
  787. }
  788. }
  789. func BenchmarkParsing(b *testing.B) {
  790. buf, err := benchmarkParsingSetup()
  791. if err != nil {
  792. b.Fatal(err)
  793. }
  794. b.ReportAllocs()
  795. for i := 0; i < b.N; i++ {
  796. benchmarkParsing(b, buf)
  797. }
  798. }
  799. func TestParsingAllocs(t *testing.T) {
  800. buf, err := benchmarkParsingSetup()
  801. if err != nil {
  802. t.Fatal(err)
  803. }
  804. if allocs := testing.AllocsPerRun(100, func() { benchmarkParsing(t, buf) }); allocs > 0.5 {
  805. t.Errorf("Allocations during parsing: got = %f, want ~0", allocs)
  806. }
  807. }
  808. func benchmarkBuildingSetup() (Name, []byte) {
  809. name := mustNewName("foo.bar.example.com.")
  810. buf := make([]byte, 0, packStartingCap)
  811. return name, buf
  812. }
  813. func benchmarkBuilding(tb testing.TB, name Name, buf []byte) {
  814. bld := NewBuilder(buf, Header{Response: true, Authoritative: true})
  815. if err := bld.StartQuestions(); err != nil {
  816. tb.Fatal("bld.StartQuestions():", err)
  817. }
  818. q := Question{
  819. Name: name,
  820. Type: TypeA,
  821. Class: ClassINET,
  822. }
  823. if err := bld.Question(q); err != nil {
  824. tb.Fatalf("bld.Question(%+v): %v", q, err)
  825. }
  826. hdr := ResourceHeader{
  827. Name: name,
  828. Class: ClassINET,
  829. }
  830. if err := bld.StartAnswers(); err != nil {
  831. tb.Fatal("bld.StartQuestions():", err)
  832. }
  833. ar := AResource{[4]byte{}}
  834. if err := bld.AResource(hdr, ar); err != nil {
  835. tb.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err)
  836. }
  837. aaar := AAAAResource{[16]byte{}}
  838. if err := bld.AAAAResource(hdr, aaar); err != nil {
  839. tb.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err)
  840. }
  841. cnr := CNAMEResource{name}
  842. if err := bld.CNAMEResource(hdr, cnr); err != nil {
  843. tb.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err)
  844. }
  845. nsr := NSResource{name}
  846. if err := bld.NSResource(hdr, nsr); err != nil {
  847. tb.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err)
  848. }
  849. if _, err := bld.Finish(); err != nil {
  850. tb.Fatal("bld.Finish():", err)
  851. }
  852. }
  853. func BenchmarkBuilding(b *testing.B) {
  854. name, buf := benchmarkBuildingSetup()
  855. b.ReportAllocs()
  856. for i := 0; i < b.N; i++ {
  857. benchmarkBuilding(b, name, buf)
  858. }
  859. }
  860. func TestBuildingAllocs(t *testing.T) {
  861. name, buf := benchmarkBuildingSetup()
  862. if allocs := testing.AllocsPerRun(100, func() { benchmarkBuilding(t, name, buf) }); allocs > 0.5 {
  863. t.Errorf("Allocations during building: got = %f, want ~0", allocs)
  864. }
  865. }
  866. func smallTestMsg() Message {
  867. name := mustNewName("example.com.")
  868. return Message{
  869. Header: Header{Response: true, Authoritative: true},
  870. Questions: []Question{
  871. {
  872. Name: name,
  873. Type: TypeA,
  874. Class: ClassINET,
  875. },
  876. },
  877. Answers: []Resource{
  878. {
  879. ResourceHeader{
  880. Name: name,
  881. Type: TypeA,
  882. Class: ClassINET,
  883. },
  884. &AResource{[4]byte{127, 0, 0, 1}},
  885. },
  886. },
  887. Authorities: []Resource{
  888. {
  889. ResourceHeader{
  890. Name: name,
  891. Type: TypeA,
  892. Class: ClassINET,
  893. },
  894. &AResource{[4]byte{127, 0, 0, 1}},
  895. },
  896. },
  897. Additionals: []Resource{
  898. {
  899. ResourceHeader{
  900. Name: name,
  901. Type: TypeA,
  902. Class: ClassINET,
  903. },
  904. &AResource{[4]byte{127, 0, 0, 1}},
  905. },
  906. },
  907. }
  908. }
  909. func BenchmarkPack(b *testing.B) {
  910. msg := largeTestMsg()
  911. b.ReportAllocs()
  912. for i := 0; i < b.N; i++ {
  913. if _, err := msg.Pack(); err != nil {
  914. b.Fatal(err)
  915. }
  916. }
  917. }
  918. func BenchmarkAppendPack(b *testing.B) {
  919. msg := largeTestMsg()
  920. buf := make([]byte, 0, packStartingCap)
  921. b.ReportAllocs()
  922. for i := 0; i < b.N; i++ {
  923. if _, err := msg.AppendPack(buf[:0]); err != nil {
  924. b.Fatal(err)
  925. }
  926. }
  927. }
  928. func largeTestMsg() Message {
  929. name := mustNewName("foo.bar.example.com.")
  930. return Message{
  931. Header: Header{Response: true, Authoritative: true},
  932. Questions: []Question{
  933. {
  934. Name: name,
  935. Type: TypeA,
  936. Class: ClassINET,
  937. },
  938. },
  939. Answers: []Resource{
  940. {
  941. ResourceHeader{
  942. Name: name,
  943. Type: TypeA,
  944. Class: ClassINET,
  945. },
  946. &AResource{[4]byte{127, 0, 0, 1}},
  947. },
  948. {
  949. ResourceHeader{
  950. Name: name,
  951. Type: TypeA,
  952. Class: ClassINET,
  953. },
  954. &AResource{[4]byte{127, 0, 0, 2}},
  955. },
  956. {
  957. ResourceHeader{
  958. Name: name,
  959. Type: TypeAAAA,
  960. Class: ClassINET,
  961. },
  962. &AAAAResource{[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
  963. },
  964. {
  965. ResourceHeader{
  966. Name: name,
  967. Type: TypeCNAME,
  968. Class: ClassINET,
  969. },
  970. &CNAMEResource{mustNewName("alias.example.com.")},
  971. },
  972. {
  973. ResourceHeader{
  974. Name: name,
  975. Type: TypeSOA,
  976. Class: ClassINET,
  977. },
  978. &SOAResource{
  979. NS: mustNewName("ns1.example.com."),
  980. MBox: mustNewName("mb.example.com."),
  981. Serial: 1,
  982. Refresh: 2,
  983. Retry: 3,
  984. Expire: 4,
  985. MinTTL: 5,
  986. },
  987. },
  988. {
  989. ResourceHeader{
  990. Name: name,
  991. Type: TypePTR,
  992. Class: ClassINET,
  993. },
  994. &PTRResource{mustNewName("ptr.example.com.")},
  995. },
  996. {
  997. ResourceHeader{
  998. Name: name,
  999. Type: TypeMX,
  1000. Class: ClassINET,
  1001. },
  1002. &MXResource{
  1003. 7,
  1004. mustNewName("mx.example.com."),
  1005. },
  1006. },
  1007. {
  1008. ResourceHeader{
  1009. Name: name,
  1010. Type: TypeSRV,
  1011. Class: ClassINET,
  1012. },
  1013. &SRVResource{
  1014. 8,
  1015. 9,
  1016. 11,
  1017. mustNewName("srv.example.com."),
  1018. },
  1019. },
  1020. },
  1021. Authorities: []Resource{
  1022. {
  1023. ResourceHeader{
  1024. Name: name,
  1025. Type: TypeNS,
  1026. Class: ClassINET,
  1027. },
  1028. &NSResource{mustNewName("ns1.example.com.")},
  1029. },
  1030. {
  1031. ResourceHeader{
  1032. Name: name,
  1033. Type: TypeNS,
  1034. Class: ClassINET,
  1035. },
  1036. &NSResource{mustNewName("ns2.example.com.")},
  1037. },
  1038. },
  1039. Additionals: []Resource{
  1040. {
  1041. ResourceHeader{
  1042. Name: name,
  1043. Type: TypeTXT,
  1044. Class: ClassINET,
  1045. },
  1046. &TXTResource{[]string{"So Long, and Thanks for All the Fish"}},
  1047. },
  1048. {
  1049. ResourceHeader{
  1050. Name: name,
  1051. Type: TypeTXT,
  1052. Class: ClassINET,
  1053. },
  1054. &TXTResource{[]string{"Hamster Huey and the Gooey Kablooie"}},
  1055. },
  1056. },
  1057. }
  1058. }