1package dns_test
2
3import (
4	"strings"
5	"testing"
6
7	"github.com/miekg/dns"
8)
9
10const TypeISBN uint16 = 0xFF00
11
12// A crazy new RR type :)
13type ISBN struct {
14	x string // rdata with 10 or 13 numbers, dashes or spaces allowed
15}
16
17func NewISBN() dns.PrivateRdata { return &ISBN{""} }
18
19func (rd *ISBN) Len() int       { return len([]byte(rd.x)) }
20func (rd *ISBN) String() string { return rd.x }
21
22func (rd *ISBN) Parse(txt []string) error {
23	rd.x = strings.TrimSpace(strings.Join(txt, " "))
24	return nil
25}
26
27func (rd *ISBN) Pack(buf []byte) (int, error) {
28	b := []byte(rd.x)
29	n := copy(buf, b)
30	if n != len(b) {
31		return n, dns.ErrBuf
32	}
33	return n, nil
34}
35
36func (rd *ISBN) Unpack(buf []byte) (int, error) {
37	rd.x = string(buf)
38	return len(buf), nil
39}
40
41func (rd *ISBN) Copy(dest dns.PrivateRdata) error {
42	isbn, ok := dest.(*ISBN)
43	if !ok {
44		return dns.ErrRdata
45	}
46	isbn.x = rd.x
47	return nil
48}
49
50var testrecord = strings.Join([]string{"example.org.", "3600", "IN", "ISBN", "12-3 456789-0-123"}, "\t")
51
52func TestPrivateText(t *testing.T) {
53	dns.PrivateHandle("ISBN", TypeISBN, NewISBN)
54	defer dns.PrivateHandleRemove(TypeISBN)
55
56	rr, err := dns.NewRR(testrecord)
57	if err != nil {
58		t.Fatal(err)
59	}
60	if rr.String() != testrecord {
61		t.Errorf("record string representation did not match original %#v != %#v", rr.String(), testrecord)
62	} else {
63		t.Log(rr.String())
64	}
65}
66
67func TestPrivateByteSlice(t *testing.T) {
68	dns.PrivateHandle("ISBN", TypeISBN, NewISBN)
69	defer dns.PrivateHandleRemove(TypeISBN)
70
71	rr, err := dns.NewRR(testrecord)
72	if err != nil {
73		t.Fatal(err)
74	}
75
76	buf := make([]byte, 100)
77	off, err := dns.PackRR(rr, buf, 0, nil, false)
78	if err != nil {
79		t.Errorf("got error packing ISBN: %v", err)
80	}
81
82	custrr := rr.(*dns.PrivateRR)
83	if ln := custrr.Data.Len() + len(custrr.Header().Name) + 11; ln != off {
84		t.Errorf("offset is not matching to length of Private RR: %d!=%d", off, ln)
85	}
86
87	rr1, off1, err := dns.UnpackRR(buf[:off], 0)
88	if err != nil {
89		t.Errorf("got error unpacking ISBN: %v", err)
90		return
91	}
92
93	if off1 != off {
94		t.Errorf("offset after unpacking differs: %d != %d", off1, off)
95	}
96
97	if rr1.String() != testrecord {
98		t.Errorf("record string representation did not match original %#v != %#v", rr1.String(), testrecord)
99	} else {
100		t.Log(rr1.String())
101	}
102}
103
104const TypeVERSION uint16 = 0xFF01
105
106type VERSION struct {
107	x string
108}
109
110func NewVersion() dns.PrivateRdata { return &VERSION{""} }
111
112func (rd *VERSION) String() string { return rd.x }
113func (rd *VERSION) Parse(txt []string) error {
114	rd.x = strings.TrimSpace(strings.Join(txt, " "))
115	return nil
116}
117
118func (rd *VERSION) Pack(buf []byte) (int, error) {
119	b := []byte(rd.x)
120	n := copy(buf, b)
121	if n != len(b) {
122		return n, dns.ErrBuf
123	}
124	return n, nil
125}
126
127func (rd *VERSION) Unpack(buf []byte) (int, error) {
128	rd.x = string(buf)
129	return len(buf), nil
130}
131
132func (rd *VERSION) Copy(dest dns.PrivateRdata) error {
133	isbn, ok := dest.(*VERSION)
134	if !ok {
135		return dns.ErrRdata
136	}
137	isbn.x = rd.x
138	return nil
139}
140
141func (rd *VERSION) Len() int {
142	return len([]byte(rd.x))
143}
144
145var smallzone = `$ORIGIN example.org.
146@ SOA	sns.dns.icann.org. noc.dns.icann.org. (
147		2014091518 7200 3600 1209600 3600
148)
149    A   1.2.3.4
150ok ISBN 1231-92110-12
151go VERSION (
152	1.3.1 ; comment
153)
154www ISBN 1231-92110-16
155*  CNAME @
156`
157
158func TestPrivateZoneParser(t *testing.T) {
159	dns.PrivateHandle("ISBN", TypeISBN, NewISBN)
160	dns.PrivateHandle("VERSION", TypeVERSION, NewVersion)
161	defer dns.PrivateHandleRemove(TypeISBN)
162	defer dns.PrivateHandleRemove(TypeVERSION)
163
164	r := strings.NewReader(smallzone)
165	for x := range dns.ParseZone(r, ".", "") {
166		if err := x.Error; err != nil {
167			t.Fatal(err)
168		}
169		t.Log(x.RR)
170	}
171}
172