message_test.go 31 KB

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