1package dns
2
3import (
4	"fmt"
5	"net"
6	"testing"
7)
8
9func BenchmarkMsgLength(b *testing.B) {
10	b.StopTimer()
11	makeMsg := func(question string, ans, ns, e []RR) *Msg {
12		msg := new(Msg)
13		msg.SetQuestion(Fqdn(question), TypeANY)
14		msg.Answer = append(msg.Answer, ans...)
15		msg.Ns = append(msg.Ns, ns...)
16		msg.Extra = append(msg.Extra, e...)
17		msg.Compress = true
18		return msg
19	}
20	name1 := "12345678901234567890123456789012345.12345678.123."
21	rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
22	msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
23	b.StartTimer()
24	for i := 0; i < b.N; i++ {
25		msg.Len()
26	}
27}
28
29func BenchmarkMsgLengthNoCompression(b *testing.B) {
30	b.StopTimer()
31	makeMsg := func(question string, ans, ns, e []RR) *Msg {
32		msg := new(Msg)
33		msg.SetQuestion(Fqdn(question), TypeANY)
34		msg.Answer = append(msg.Answer, ans...)
35		msg.Ns = append(msg.Ns, ns...)
36		msg.Extra = append(msg.Extra, e...)
37		return msg
38	}
39	name1 := "12345678901234567890123456789012345.12345678.123."
40	rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
41	msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
42	b.StartTimer()
43	for i := 0; i < b.N; i++ {
44		msg.Len()
45	}
46}
47
48func BenchmarkMsgLengthPack(b *testing.B) {
49	makeMsg := func(question string, ans, ns, e []RR) *Msg {
50		msg := new(Msg)
51		msg.SetQuestion(Fqdn(question), TypeANY)
52		msg.Answer = append(msg.Answer, ans...)
53		msg.Ns = append(msg.Ns, ns...)
54		msg.Extra = append(msg.Extra, e...)
55		msg.Compress = true
56		return msg
57	}
58	name1 := "12345678901234567890123456789012345.12345678.123."
59	rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
60	msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
61	b.ResetTimer()
62	for i := 0; i < b.N; i++ {
63		_, _ = msg.Pack()
64	}
65}
66
67func BenchmarkMsgLengthMassive(b *testing.B) {
68	makeMsg := func(question string, ans, ns, e []RR) *Msg {
69		msg := new(Msg)
70		msg.SetQuestion(Fqdn(question), TypeANY)
71		msg.Answer = append(msg.Answer, ans...)
72		msg.Ns = append(msg.Ns, ns...)
73		msg.Extra = append(msg.Extra, e...)
74		msg.Compress = true
75		return msg
76	}
77	const name1 = "12345678901234567890123456789012345.12345678.123."
78	rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
79	answer := []RR{rrMx, rrMx}
80	for i := 0; i < 128; i++ {
81		rrA := testRR(fmt.Sprintf("example%03d.something%03delse.org. 2311 IN A 127.0.0.1", i/32, i%32))
82		answer = append(answer, rrA)
83	}
84	answer = append(answer, rrMx, rrMx)
85	msg := makeMsg(name1, answer, nil, nil)
86	b.ResetTimer()
87	for i := 0; i < b.N; i++ {
88		msg.Len()
89	}
90}
91
92func BenchmarkMsgLengthOnlyQuestion(b *testing.B) {
93	msg := new(Msg)
94	msg.SetQuestion(Fqdn("12345678901234567890123456789012345.12345678.123."), TypeANY)
95	msg.Compress = true
96	b.ResetTimer()
97	for i := 0; i < b.N; i++ {
98		msg.Len()
99	}
100}
101
102func BenchmarkMsgLengthEscapedName(b *testing.B) {
103	msg := new(Msg)
104	msg.SetQuestion(`\1\2\3\4\5\6\7\8\9\0\1\2\3\4\5\6\7\8\9\0\1\2\3\4\5\6\7\8\9\0\1\2\3\4\5.\1\2\3\4\5\6\7\8.\1\2\3.`, TypeANY)
105	b.ResetTimer()
106	for i := 0; i < b.N; i++ {
107		msg.Len()
108	}
109}
110
111func BenchmarkPackDomainName(b *testing.B) {
112	name1 := "12345678901234567890123456789012345.12345678.123."
113	buf := make([]byte, len(name1)+1)
114	b.ResetTimer()
115	for i := 0; i < b.N; i++ {
116		_, _ = PackDomainName(name1, buf, 0, nil, false)
117	}
118}
119
120func BenchmarkUnpackDomainName(b *testing.B) {
121	name1 := "12345678901234567890123456789012345.12345678.123."
122	buf := make([]byte, len(name1)+1)
123	_, _ = PackDomainName(name1, buf, 0, nil, false)
124	b.ResetTimer()
125	for i := 0; i < b.N; i++ {
126		_, _, _ = UnpackDomainName(buf, 0)
127	}
128}
129
130func BenchmarkUnpackDomainNameUnprintable(b *testing.B) {
131	name1 := "\x02\x02\x02\x025\x02\x02\x02\x02.12345678.123."
132	buf := make([]byte, len(name1)+1)
133	_, _ = PackDomainName(name1, buf, 0, nil, false)
134	b.ResetTimer()
135	for i := 0; i < b.N; i++ {
136		_, _, _ = UnpackDomainName(buf, 0)
137	}
138}
139
140func BenchmarkUnpackDomainNameLongest(b *testing.B) {
141	buf := make([]byte, len(longestDomain)+1)
142	n, err := PackDomainName(longestDomain, buf, 0, nil, false)
143	if err != nil {
144		b.Fatal(err)
145	}
146	if n != maxDomainNameWireOctets {
147		b.Fatalf("name wrong size in wire format, expected %d, got %d", maxDomainNameWireOctets, n)
148	}
149	b.ResetTimer()
150	for i := 0; i < b.N; i++ {
151		_, _, _ = UnpackDomainName(buf, 0)
152	}
153}
154
155func BenchmarkUnpackDomainNameLongestUnprintable(b *testing.B) {
156	buf := make([]byte, len(longestUnprintableDomain)+1)
157	n, err := PackDomainName(longestUnprintableDomain, buf, 0, nil, false)
158	if err != nil {
159		b.Fatal(err)
160	}
161	if n != maxDomainNameWireOctets {
162		b.Fatalf("name wrong size in wire format, expected %d, got %d", maxDomainNameWireOctets, n)
163	}
164	b.ResetTimer()
165	for i := 0; i < b.N; i++ {
166		_, _, _ = UnpackDomainName(buf, 0)
167	}
168}
169
170func BenchmarkCopy(b *testing.B) {
171	b.ReportAllocs()
172	m := new(Msg)
173	m.SetQuestion("miek.nl.", TypeA)
174	rr := testRR("miek.nl. 2311 IN A 127.0.0.1")
175	m.Answer = []RR{rr}
176	rr = testRR("miek.nl. 2311 IN NS 127.0.0.1")
177	m.Ns = []RR{rr}
178	rr = testRR("miek.nl. 2311 IN A 127.0.0.1")
179	m.Extra = []RR{rr}
180
181	b.ResetTimer()
182	for i := 0; i < b.N; i++ {
183		m.Copy()
184	}
185}
186
187func BenchmarkPackA(b *testing.B) {
188	a := &A{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, A: net.IPv4(127, 0, 0, 1)}
189
190	buf := make([]byte, Len(a))
191	b.ReportAllocs()
192	b.ResetTimer()
193	for i := 0; i < b.N; i++ {
194		_, _ = PackRR(a, buf, 0, nil, false)
195	}
196}
197
198func BenchmarkUnpackA(b *testing.B) {
199	a := &A{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, A: net.IPv4(127, 0, 0, 1)}
200
201	buf := make([]byte, Len(a))
202	PackRR(a, buf, 0, nil, false)
203	a = nil
204	b.ReportAllocs()
205	b.ResetTimer()
206	for i := 0; i < b.N; i++ {
207		_, _, _ = UnpackRR(buf, 0)
208	}
209}
210
211func BenchmarkPackMX(b *testing.B) {
212	m := &MX{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, Mx: "mx.miek.nl."}
213
214	buf := make([]byte, Len(m))
215	b.ReportAllocs()
216	b.ResetTimer()
217	for i := 0; i < b.N; i++ {
218		_, _ = PackRR(m, buf, 0, nil, false)
219	}
220}
221
222func BenchmarkUnpackMX(b *testing.B) {
223	m := &MX{Hdr: RR_Header{Name: ".", Rrtype: TypeA, Class: ClassANY}, Mx: "mx.miek.nl."}
224
225	buf := make([]byte, Len(m))
226	PackRR(m, buf, 0, nil, false)
227	m = nil
228	b.ReportAllocs()
229	b.ResetTimer()
230	for i := 0; i < b.N; i++ {
231		_, _, _ = UnpackRR(buf, 0)
232	}
233}
234
235func BenchmarkPackAAAAA(b *testing.B) {
236	aaaa := testRR(". IN AAAA ::1")
237
238	buf := make([]byte, Len(aaaa))
239	b.ReportAllocs()
240	b.ResetTimer()
241	for i := 0; i < b.N; i++ {
242		_, _ = PackRR(aaaa, buf, 0, nil, false)
243	}
244}
245
246func BenchmarkUnpackAAAA(b *testing.B) {
247	aaaa := testRR(". IN AAAA ::1")
248
249	buf := make([]byte, Len(aaaa))
250	PackRR(aaaa, buf, 0, nil, false)
251	aaaa = nil
252	b.ReportAllocs()
253	b.ResetTimer()
254	for i := 0; i < b.N; i++ {
255		_, _, _ = UnpackRR(buf, 0)
256	}
257}
258
259func BenchmarkPackMsg(b *testing.B) {
260	makeMsg := func(question string, ans, ns, e []RR) *Msg {
261		msg := new(Msg)
262		msg.SetQuestion(Fqdn(question), TypeANY)
263		msg.Answer = append(msg.Answer, ans...)
264		msg.Ns = append(msg.Ns, ns...)
265		msg.Extra = append(msg.Extra, e...)
266		msg.Compress = true
267		return msg
268	}
269	name1 := "12345678901234567890123456789012345.12345678.123."
270	rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
271	msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
272	buf := make([]byte, 512)
273	b.ReportAllocs()
274	b.ResetTimer()
275	for i := 0; i < b.N; i++ {
276		_, _ = msg.PackBuffer(buf)
277	}
278}
279
280func BenchmarkPackMsgMassive(b *testing.B) {
281	makeMsg := func(question string, ans, ns, e []RR) *Msg {
282		msg := new(Msg)
283		msg.SetQuestion(Fqdn(question), TypeANY)
284		msg.Answer = append(msg.Answer, ans...)
285		msg.Ns = append(msg.Ns, ns...)
286		msg.Extra = append(msg.Extra, e...)
287		msg.Compress = true
288		return msg
289	}
290	const name1 = "12345678901234567890123456789012345.12345678.123."
291	rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
292	answer := []RR{rrMx, rrMx}
293	for i := 0; i < 128; i++ {
294		rrA := testRR(fmt.Sprintf("example%03d.something%03delse.org. 2311 IN A 127.0.0.1", i/32, i%32))
295		answer = append(answer, rrA)
296	}
297	answer = append(answer, rrMx, rrMx)
298	msg := makeMsg(name1, answer, nil, nil)
299	buf := make([]byte, 512)
300	b.ReportAllocs()
301	b.ResetTimer()
302	for i := 0; i < b.N; i++ {
303		_, _ = msg.PackBuffer(buf)
304	}
305}
306
307func BenchmarkPackMsgOnlyQuestion(b *testing.B) {
308	msg := new(Msg)
309	msg.SetQuestion(Fqdn("12345678901234567890123456789012345.12345678.123."), TypeANY)
310	msg.Compress = true
311	buf := make([]byte, 512)
312	b.ReportAllocs()
313	b.ResetTimer()
314	for i := 0; i < b.N; i++ {
315		_, _ = msg.PackBuffer(buf)
316	}
317}
318
319func BenchmarkUnpackMsg(b *testing.B) {
320	makeMsg := func(question string, ans, ns, e []RR) *Msg {
321		msg := new(Msg)
322		msg.SetQuestion(Fqdn(question), TypeANY)
323		msg.Answer = append(msg.Answer, ans...)
324		msg.Ns = append(msg.Ns, ns...)
325		msg.Extra = append(msg.Extra, e...)
326		msg.Compress = true
327		return msg
328	}
329	name1 := "12345678901234567890123456789012345.12345678.123."
330	rrMx := testRR(name1 + " 3600 IN MX 10 " + name1)
331	msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
332	msgBuf, _ := msg.Pack()
333	b.ReportAllocs()
334	b.ResetTimer()
335	for i := 0; i < b.N; i++ {
336		_ = msg.Unpack(msgBuf)
337	}
338}
339
340func BenchmarkIdGeneration(b *testing.B) {
341	for i := 0; i < b.N; i++ {
342		_ = id()
343	}
344}
345
346func BenchmarkReverseAddr(b *testing.B) {
347	b.Run("IP4", func(b *testing.B) {
348		for n := 0; n < b.N; n++ {
349			addr, err := ReverseAddr("192.0.2.1")
350			if err != nil {
351				b.Fatal(err)
352			}
353			if expect := "1.2.0.192.in-addr.arpa."; addr != expect {
354				b.Fatalf("invalid reverse address, expected %q, got %q", expect, addr)
355			}
356		}
357	})
358
359	b.Run("IP6", func(b *testing.B) {
360		for n := 0; n < b.N; n++ {
361			addr, err := ReverseAddr("2001:db8::68")
362			if err != nil {
363				b.Fatal(err)
364			}
365			if expect := "8.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa."; addr != expect {
366				b.Fatalf("invalid reverse address, expected %q, got %q", expect, addr)
367			}
368		}
369	})
370}
371