7a2b79a8ffe16d9f3a42d0d2e36a25533204677a
[platform/core/system/edge-orchestration.git] / vendor / github.com / miekg / dns / length_test.go
1 package dns
2
3 import (
4         "encoding/hex"
5         "fmt"
6         "net"
7         "strings"
8         "testing"
9 )
10
11 func TestCompressLength(t *testing.T) {
12         m := new(Msg)
13         m.SetQuestion("miek.nl.", TypeMX)
14         ul := m.Len()
15         m.Compress = true
16         if ul != m.Len() {
17                 t.Fatalf("should be equal")
18         }
19 }
20
21 // Does the predicted length match final packed length?
22 func TestMsgCompressLength(t *testing.T) {
23         makeMsg := func(question string, ans, ns, e []RR) *Msg {
24                 msg := new(Msg)
25                 msg.SetQuestion(Fqdn(question), TypeANY)
26                 msg.Answer = append(msg.Answer, ans...)
27                 msg.Ns = append(msg.Ns, ns...)
28                 msg.Extra = append(msg.Extra, e...)
29                 msg.Compress = true
30                 return msg
31         }
32
33         name1 := "12345678901234567890123456789012345.12345678.123."
34         rrA := testRR(name1 + " 3600 IN A 192.0.2.1")
35         rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
36         tests := []*Msg{
37                 makeMsg(name1, []RR{rrA}, nil, nil),
38                 makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)}
39
40         for _, msg := range tests {
41                 predicted := msg.Len()
42                 buf, err := msg.Pack()
43                 if err != nil {
44                         t.Error(err)
45                 }
46                 if predicted < len(buf) {
47                         t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d",
48                                 msg.Question[0].Name, len(msg.Answer), predicted, len(buf))
49                 }
50         }
51 }
52
53 func TestMsgLength(t *testing.T) {
54         makeMsg := func(question string, ans, ns, e []RR) *Msg {
55                 msg := new(Msg)
56                 msg.Compress = true
57                 msg.SetQuestion(Fqdn(question), TypeANY)
58                 msg.Answer = append(msg.Answer, ans...)
59                 msg.Ns = append(msg.Ns, ns...)
60                 msg.Extra = append(msg.Extra, e...)
61                 return msg
62         }
63
64         name1 := "12345678901234567890123456789012345.12345678.123."
65         rrA := testRR(name1 + " 3600 IN A 192.0.2.1")
66         rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
67         tests := []*Msg{
68                 makeMsg(name1, []RR{rrA}, nil, nil),
69                 makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)}
70
71         for _, msg := range tests {
72                 predicted := msg.Len()
73                 buf, err := msg.Pack()
74                 if err != nil {
75                         t.Error(err)
76                 }
77                 if predicted < len(buf) {
78                         t.Errorf("predicted length is wrong: predicted %s (len=%d), actual %d",
79                                 msg.Question[0].Name, predicted, len(buf))
80                 }
81         }
82 }
83
84 func TestCompressionLenSearchInsert(t *testing.T) {
85         c := make(map[string]struct{})
86         compressionLenSearch(c, "example.com", 12)
87         if _, ok := c["example.com"]; !ok {
88                 t.Errorf("bad example.com")
89         }
90         if _, ok := c["com"]; !ok {
91                 t.Errorf("bad com")
92         }
93
94         // Test boundaries
95         c = make(map[string]struct{})
96         // foo label starts at 16379
97         // com label starts at 16384
98         compressionLenSearch(c, "foo.com", 16379)
99         if _, ok := c["foo.com"]; !ok {
100                 t.Errorf("bad foo.com")
101         }
102         // com label is accessible
103         if _, ok := c["com"]; !ok {
104                 t.Errorf("bad com")
105         }
106
107         c = make(map[string]struct{})
108         // foo label starts at 16379
109         // com label starts at 16385 => outside range
110         compressionLenSearch(c, "foo.com", 16380)
111         if _, ok := c["foo.com"]; !ok {
112                 t.Errorf("bad foo.com")
113         }
114         // com label is NOT accessible
115         if _, ok := c["com"]; ok {
116                 t.Errorf("bad com")
117         }
118
119         c = make(map[string]struct{})
120         compressionLenSearch(c, "example.com", 16375)
121         if _, ok := c["example.com"]; !ok {
122                 t.Errorf("bad example.com")
123         }
124         // com starts AFTER 16384
125         if _, ok := c["com"]; !ok {
126                 t.Errorf("bad com")
127         }
128
129         c = make(map[string]struct{})
130         compressionLenSearch(c, "example.com", 16376)
131         if _, ok := c["example.com"]; !ok {
132                 t.Errorf("bad example.com")
133         }
134         // com starts AFTER 16384
135         if _, ok := c["com"]; ok {
136                 t.Errorf("bad com")
137         }
138 }
139
140 func TestCompressionLenSearch(t *testing.T) {
141         c := make(map[string]struct{})
142         compressed, ok := compressionLenSearch(c, "a.b.org.", maxCompressionOffset)
143         if compressed != 0 || ok {
144                 t.Errorf("Failed: compressed:=%d, ok:=%v", compressed, ok)
145         }
146         c["org."] = struct{}{}
147         compressed, ok = compressionLenSearch(c, "a.b.org.", maxCompressionOffset)
148         if compressed != 4 || !ok {
149                 t.Errorf("Failed: compressed:=%d, ok:=%v", compressed, ok)
150         }
151         c["b.org."] = struct{}{}
152         compressed, ok = compressionLenSearch(c, "a.b.org.", maxCompressionOffset)
153         if compressed != 2 || !ok {
154                 t.Errorf("Failed: compressed:=%d, ok:=%v", compressed, ok)
155         }
156         // Not found long compression
157         c["x.b.org."] = struct{}{}
158         compressed, ok = compressionLenSearch(c, "a.b.org.", maxCompressionOffset)
159         if compressed != 2 || !ok {
160                 t.Errorf("Failed: compressed:=%d, ok:=%v", compressed, ok)
161         }
162         // Found long compression
163         c["a.b.org."] = struct{}{}
164         compressed, ok = compressionLenSearch(c, "a.b.org.", maxCompressionOffset)
165         if compressed != 0 || !ok {
166                 t.Errorf("Failed: compressed:=%d, ok:=%v", compressed, ok)
167         }
168 }
169
170 func TestMsgLength2(t *testing.T) {
171         // Serialized replies
172         var testMessages = []string{
173                 // google.com. IN A?
174                 "064e81800001000b0004000506676f6f676c6503636f6d0000010001c00c00010001000000050004adc22986c00c00010001000000050004adc22987c00c00010001000000050004adc22988c00c00010001000000050004adc22989c00c00010001000000050004adc2298ec00c00010001000000050004adc22980c00c00010001000000050004adc22981c00c00010001000000050004adc22982c00c00010001000000050004adc22983c00c00010001000000050004adc22984c00c00010001000000050004adc22985c00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc0d800010001000000050004d8ef200ac0ea00010001000000050004d8ef220ac0fc00010001000000050004d8ef240ac10e00010001000000050004d8ef260a0000290500000000050000",
175                 // amazon.com. IN A? (reply has no EDNS0 record)
176                 "6de1818000010004000a000806616d617a6f6e03636f6d0000010001c00c000100010000000500044815c2d4c00c000100010000000500044815d7e8c00c00010001000000050004b02062a6c00c00010001000000050004cdfbf236c00c000200010000000500140570646e733408756c747261646e73036f726700c00c000200010000000500150570646e733508756c747261646e7304696e666f00c00c000200010000000500160570646e733608756c747261646e7302636f02756b00c00c00020001000000050014036e7331037033310664796e656374036e657400c00c00020001000000050006036e7332c0cfc00c00020001000000050006036e7333c0cfc00c00020001000000050006036e7334c0cfc00c000200010000000500110570646e733108756c747261646e73c0dac00c000200010000000500080570646e7332c127c00c000200010000000500080570646e7333c06ec0cb00010001000000050004d04e461fc0eb00010001000000050004cc0dfa1fc0fd00010001000000050004d04e471fc10f00010001000000050004cc0dfb1fc12100010001000000050004cc4a6c01c121001c000100000005001020010502f3ff00000000000000000001c13e00010001000000050004cc4a6d01c13e001c0001000000050010261000a1101400000000000000000001",
177                 // yahoo.com. IN A?
178                 "fc2d81800001000300070008057961686f6f03636f6d0000010001c00c00010001000000050004628afd6dc00c00010001000000050004628bb718c00c00010001000000050004cebe242dc00c00020001000000050006036e7336c00cc00c00020001000000050006036e7338c00cc00c00020001000000050006036e7331c00cc00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7335c00cc07b0001000100000005000444b48310c08d00010001000000050004448eff10c09f00010001000000050004cb54dd35c0b100010001000000050004628a0b9dc0c30001000100000005000477a0f77cc05700010001000000050004ca2bdfaac06900010001000000050004caa568160000290500000000050000",
179                 // microsoft.com. IN A?
180                 "f4368180000100020005000b096d6963726f736f667403636f6d0000010001c00c0001000100000005000440040b25c00c0001000100000005000441373ac9c00c0002000100000005000e036e7331046d736674036e657400c00c00020001000000050006036e7332c04fc00c00020001000000050006036e7333c04fc00c00020001000000050006036e7334c04fc00c00020001000000050006036e7335c04fc04b000100010000000500044137253ec04b001c00010000000500102a010111200500000000000000010001c0650001000100000005000440043badc065001c00010000000500102a010111200600060000000000010001c07700010001000000050004d5c7b435c077001c00010000000500102a010111202000000000000000010001c08900010001000000050004cf2e4bfec089001c00010000000500102404f800200300000000000000010001c09b000100010000000500044137e28cc09b001c00010000000500102a010111200f000100000000000100010000290500000000050000",
181                 // google.com. IN MX?
182                 "724b8180000100050004000b06676f6f676c6503636f6d00000f0001c00c000f000100000005000c000a056173706d78016cc00cc00c000f0001000000050009001404616c7431c02ac00c000f0001000000050009001e04616c7432c02ac00c000f0001000000050009002804616c7433c02ac00c000f0001000000050009003204616c7434c02ac00c00020001000000050006036e7332c00cc00c00020001000000050006036e7333c00cc00c00020001000000050006036e7334c00cc00c00020001000000050006036e7331c00cc02a00010001000000050004adc2421bc02a001c00010000000500102a00145040080c01000000000000001bc04200010001000000050004adc2461bc05700010001000000050004adc2451bc06c000100010000000500044a7d8f1bc081000100010000000500044a7d191bc0ca00010001000000050004d8ef200ac09400010001000000050004d8ef220ac0a600010001000000050004d8ef240ac0b800010001000000050004d8ef260a0000290500000000050000",
183                 // reddit.com. IN A?
184                 "12b98180000100080000000c0672656464697403636f6d0000020001c00c0002000100000005000f046175733204616b616d036e657400c00c000200010000000500070475736534c02dc00c000200010000000500070475737733c02dc00c000200010000000500070475737735c02dc00c00020001000000050008056173696131c02dc00c00020001000000050008056173696139c02dc00c00020001000000050008056e73312d31c02dc00c0002000100000005000a076e73312d313935c02dc02800010001000000050004c30a242ec04300010001000000050004451f1d39c05600010001000000050004451f3bc7c0690001000100000005000460073240c07c000100010000000500046007fb81c090000100010000000500047c283484c090001c00010000000500102a0226f0006700000000000000000064c0a400010001000000050004c16c5b01c0a4001c000100000005001026001401000200000000000000000001c0b800010001000000050004c16c5bc3c0b8001c0001000000050010260014010002000000000000000000c30000290500000000050000",
185         }
186
187         for i, hexData := range testMessages {
188                 // we won't fail the decoding of the hex
189                 input, _ := hex.DecodeString(hexData)
190
191                 m := new(Msg)
192                 m.Unpack(input)
193                 m.Compress = true
194                 lenComp := m.Len()
195                 b, _ := m.Pack()
196                 pacComp := len(b)
197                 m.Compress = false
198                 lenUnComp := m.Len()
199                 b, _ = m.Pack()
200                 pacUnComp := len(b)
201                 if pacComp != lenComp {
202                         t.Errorf("msg.Len(compressed)=%d actual=%d for test %d", lenComp, pacComp, i)
203                 }
204                 if pacUnComp != lenUnComp {
205                         t.Errorf("msg.Len(uncompressed)=%d actual=%d for test %d", lenUnComp, pacUnComp, i)
206                 }
207         }
208 }
209
210 func TestMsgLengthCompressionMalformed(t *testing.T) {
211         // SOA with empty hostmaster, which is illegal
212         soa := &SOA{Hdr: RR_Header{Name: ".", Rrtype: TypeSOA, Class: ClassINET, Ttl: 12345},
213                 Ns:      ".",
214                 Mbox:    "",
215                 Serial:  0,
216                 Refresh: 28800,
217                 Retry:   7200,
218                 Expire:  604800,
219                 Minttl:  60}
220         m := new(Msg)
221         m.Compress = true
222         m.Ns = []RR{soa}
223         m.Len() // Should not crash.
224 }
225
226 func TestMsgCompressLength2(t *testing.T) {
227         msg := new(Msg)
228         msg.Compress = true
229         msg.SetQuestion(Fqdn("bliep."), TypeANY)
230         msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "blaat.", Rrtype: 0x21, Class: 0x1, Ttl: 0x3c}, Port: 0x4c57, Target: "foo.bar."})
231         msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: "foo.bar.", Rrtype: 0x1, Class: 0x1, Ttl: 0x3c}, A: net.IP{0xac, 0x11, 0x0, 0x3}})
232         predicted := msg.Len()
233         buf, err := msg.Pack()
234         if err != nil {
235                 t.Error(err)
236         }
237         if predicted != len(buf) {
238                 t.Errorf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d",
239                         msg.Question[0].Name, len(msg.Answer), predicted, len(buf))
240         }
241 }
242
243 func TestMsgCompressLengthLargeRecords(t *testing.T) {
244         msg := new(Msg)
245         msg.Compress = true
246         msg.SetQuestion("my.service.acme.", TypeSRV)
247         j := 1
248         for i := 0; i < 250; i++ {
249                 target := fmt.Sprintf("host-redis-1-%d.test.acme.com.node.dc1.consul.", i)
250                 msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target})
251                 msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: 1, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", j, i)})
252         }
253         predicted := msg.Len()
254         buf, err := msg.Pack()
255         if err != nil {
256                 t.Error(err)
257         }
258         if predicted != len(buf) {
259                 t.Fatalf("predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", msg.Question[0].Name, len(msg.Answer), predicted, len(buf))
260         }
261 }
262
263 func compressionMapsEqual(a map[string]struct{}, b map[string]int) bool {
264         if len(a) != len(b) {
265                 return false
266         }
267
268         for k := range a {
269                 if _, ok := b[k]; !ok {
270                         return false
271                 }
272         }
273
274         return true
275 }
276
277 func compressionMapsDifference(a map[string]struct{}, b map[string]int) string {
278         var s strings.Builder
279
280         var c int
281         fmt.Fprintf(&s, "length compression map (%d):", len(a))
282         for k := range b {
283                 if _, ok := a[k]; !ok {
284                         if c > 0 {
285                                 s.WriteString(",")
286                         }
287
288                         fmt.Fprintf(&s, " missing %q", k)
289                         c++
290                 }
291         }
292
293         c = 0
294         fmt.Fprintf(&s, "\npack compression map (%d):", len(b))
295         for k := range a {
296                 if _, ok := b[k]; !ok {
297                         if c > 0 {
298                                 s.WriteString(",")
299                         }
300
301                         fmt.Fprintf(&s, " missing %q", k)
302                         c++
303                 }
304         }
305
306         return s.String()
307 }
308
309 func TestCompareCompressionMapsForANY(t *testing.T) {
310         msg := new(Msg)
311         msg.Compress = true
312         msg.SetQuestion("a.service.acme.", TypeANY)
313         // Be sure to have more than 14bits
314         for i := 0; i < 2000; i++ {
315                 target := fmt.Sprintf("host.app-%d.x%d.test.acme.", i%250, i)
316                 msg.Answer = append(msg.Answer, &AAAA{Hdr: RR_Header{Name: target, Rrtype: TypeAAAA, Class: ClassINET, Ttl: 0x3c}, AAAA: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, byte(i / 255), byte(i % 255)}})
317                 msg.Answer = append(msg.Answer, &A{Hdr: RR_Header{Name: target, Rrtype: TypeA, Class: ClassINET, Ttl: 0x3c}, A: net.IP{127, 0, byte(i / 255), byte(i % 255)}})
318                 if msg.Len() > 16384 {
319                         break
320                 }
321         }
322         for labelSize := 0; labelSize < 63; labelSize++ {
323                 msg.SetQuestion(fmt.Sprintf("a%s.service.acme.", strings.Repeat("x", labelSize)), TypeANY)
324
325                 compressionFake := make(map[string]struct{})
326                 lenFake := msgLenWithCompressionMap(msg, compressionFake)
327
328                 compressionReal := make(map[string]int)
329                 buf, err := msg.packBufferWithCompressionMap(nil, compressionMap{ext: compressionReal}, true)
330                 if err != nil {
331                         t.Fatal(err)
332                 }
333                 if lenFake != len(buf) {
334                         t.Fatalf("padding= %d ; Predicted len := %d != real:= %d", labelSize, lenFake, len(buf))
335                 }
336                 if !compressionMapsEqual(compressionFake, compressionReal) {
337                         t.Fatalf("padding= %d ; Fake Compression Map != Real Compression Map\n%s", labelSize, compressionMapsDifference(compressionFake, compressionReal))
338                 }
339         }
340 }
341
342 func TestCompareCompressionMapsForSRV(t *testing.T) {
343         msg := new(Msg)
344         msg.Compress = true
345         msg.SetQuestion("a.service.acme.", TypeSRV)
346         // Be sure to have more than 14bits
347         for i := 0; i < 2000; i++ {
348                 target := fmt.Sprintf("host.app-%d.x%d.test.acme.", i%250, i)
349                 msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: ClassINET, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target})
350                 msg.Extra = append(msg.Extra, &A{Hdr: RR_Header{Name: target, Rrtype: TypeA, Class: ClassINET, Ttl: 0x3c}, A: net.IP{127, 0, byte(i / 255), byte(i % 255)}})
351                 if msg.Len() > 16384 {
352                         break
353                 }
354         }
355         for labelSize := 0; labelSize < 63; labelSize++ {
356                 msg.SetQuestion(fmt.Sprintf("a%s.service.acme.", strings.Repeat("x", labelSize)), TypeAAAA)
357
358                 compressionFake := make(map[string]struct{})
359                 lenFake := msgLenWithCompressionMap(msg, compressionFake)
360
361                 compressionReal := make(map[string]int)
362                 buf, err := msg.packBufferWithCompressionMap(nil, compressionMap{ext: compressionReal}, true)
363                 if err != nil {
364                         t.Fatal(err)
365                 }
366                 if lenFake != len(buf) {
367                         t.Fatalf("padding= %d ; Predicted len := %d != real:= %d", labelSize, lenFake, len(buf))
368                 }
369                 if !compressionMapsEqual(compressionFake, compressionReal) {
370                         t.Fatalf("padding= %d ; Fake Compression Map != Real Compression Map\n%s", labelSize, compressionMapsDifference(compressionFake, compressionReal))
371                 }
372         }
373 }
374
375 func TestMsgCompressLengthLargeRecordsWithPaddingPermutation(t *testing.T) {
376         msg := new(Msg)
377         msg.Compress = true
378         msg.SetQuestion("my.service.acme.", TypeSRV)
379
380         for i := 0; i < 250; i++ {
381                 target := fmt.Sprintf("host-redis-x-%d.test.acme.com.node.dc1.consul.", i)
382                 msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target})
383                 msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: ClassINET, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.x.%d.", i)})
384         }
385         for labelSize := 1; labelSize < 63; labelSize++ {
386                 msg.SetQuestion(fmt.Sprintf("my.%s.service.acme.", strings.Repeat("x", labelSize)), TypeSRV)
387                 predicted := msg.Len()
388                 buf, err := msg.Pack()
389                 if err != nil {
390                         t.Error(err)
391                 }
392                 if predicted != len(buf) {
393                         t.Fatalf("padding= %d ; predicted compressed length is wrong: predicted %s (len=%d) %d, actual %d", labelSize, msg.Question[0].Name, len(msg.Answer), predicted, len(buf))
394                 }
395         }
396 }
397
398 func TestMsgCompressLengthLargeRecordsAllValues(t *testing.T) {
399         msg := new(Msg)
400         msg.Compress = true
401         msg.SetQuestion("redis.service.consul.", TypeSRV)
402         for i := 0; i < 900; i++ {
403                 target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", i/256, i%256)
404                 msg.Answer = append(msg.Answer, &SRV{Hdr: RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target})
405                 msg.Extra = append(msg.Extra, &CNAME{Hdr: RR_Header{Name: target, Class: ClassINET, Rrtype: TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)})
406                 predicted := msg.Len()
407                 buf, err := msg.Pack()
408                 if err != nil {
409                         t.Error(err)
410                 }
411                 if predicted != len(buf) {
412                         t.Fatalf("predicted compressed length is wrong for %d records: predicted %s (len=%d) %d, actual %d", i, msg.Question[0].Name, len(msg.Answer), predicted, len(buf))
413                 }
414         }
415 }
416
417 func TestMsgCompressionMultipleQuestions(t *testing.T) {
418         msg := new(Msg)
419         msg.Compress = true
420         msg.SetQuestion("www.example.org.", TypeA)
421         msg.Question = append(msg.Question, Question{"other.example.org.", TypeA, ClassINET})
422
423         predicted := msg.Len()
424         buf, err := msg.Pack()
425         if err != nil {
426                 t.Error(err)
427         }
428         if predicted != len(buf) {
429                 t.Fatalf("predicted compressed length is wrong: predicted %d, actual %d", predicted, len(buf))
430         }
431 }
432
433 func TestMsgCompressMultipleCompressedNames(t *testing.T) {
434         msg := new(Msg)
435         msg.Compress = true
436         msg.SetQuestion("www.example.com.", TypeSRV)
437         msg.Answer = append(msg.Answer, &MINFO{
438                 Hdr:   RR_Header{Name: "www.example.com.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c},
439                 Rmail: "mail.example.org.",
440                 Email: "mail.example.org.",
441         })
442         msg.Answer = append(msg.Answer, &SOA{
443                 Hdr:  RR_Header{Name: "www.example.com.", Class: 1, Rrtype: TypeSRV, Ttl: 0x3c},
444                 Ns:   "ns.example.net.",
445                 Mbox: "mail.example.net.",
446         })
447
448         predicted := msg.Len()
449         buf, err := msg.Pack()
450         if err != nil {
451                 t.Error(err)
452         }
453         if predicted != len(buf) {
454                 t.Fatalf("predicted compressed length is wrong: predicted %d, actual %d", predicted, len(buf))
455         }
456 }
457
458 func TestMsgCompressLengthEscapingMatch(t *testing.T) {
459         // Although slightly non-optimal, "example.org." and "ex\\097mple.org."
460         // are not considered equal in the compression map, even though \097 is
461         // a valid escaping of a. This test ensures that the Len code and the
462         // Pack code don't disagree on this.
463
464         msg := new(Msg)
465         msg.Compress = true
466         msg.SetQuestion("www.example.org.", TypeA)
467         msg.Answer = append(msg.Answer, &NS{Hdr: RR_Header{Name: "ex\\097mple.org.", Rrtype: TypeNS, Class: ClassINET}, Ns: "ns.example.org."})
468
469         predicted := msg.Len()
470         buf, err := msg.Pack()
471         if err != nil {
472                 t.Error(err)
473         }
474         if predicted != len(buf) {
475                 t.Fatalf("predicted compressed length is wrong: predicted %d, actual %d", predicted, len(buf))
476         }
477 }
478
479 func TestMsgLengthEscaped(t *testing.T) {
480         msg := new(Msg)
481         msg.SetQuestion(`\000\001\002.\003\004\005\006\007\008\009.\a\b\c.`, TypeA)
482
483         predicted := msg.Len()
484         buf, err := msg.Pack()
485         if err != nil {
486                 t.Error(err)
487         }
488         if predicted != len(buf) {
489                 t.Fatalf("predicted compressed length is wrong: predicted %d, actual %d", predicted, len(buf))
490         }
491 }
492
493 func TestMsgCompressLengthEscaped(t *testing.T) {
494         msg := new(Msg)
495         msg.Compress = true
496         msg.SetQuestion("www.example.org.", TypeA)
497         msg.Answer = append(msg.Answer, &NS{Hdr: RR_Header{Name: `\000\001\002.example.org.`, Rrtype: TypeNS, Class: ClassINET}, Ns: `ns.\e\x\a\m\p\l\e.org.`})
498         msg.Answer = append(msg.Answer, &NS{Hdr: RR_Header{Name: `www.\e\x\a\m\p\l\e.org.`, Rrtype: TypeNS, Class: ClassINET}, Ns: "ns.example.org."})
499
500         predicted := msg.Len()
501         buf, err := msg.Pack()
502         if err != nil {
503                 t.Error(err)
504         }
505         if predicted != len(buf) {
506                 t.Fatalf("predicted compressed length is wrong: predicted %d, actual %d", predicted, len(buf))
507         }
508 }