message_test.go 25 KB

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