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	}
63}
64
65func TestPrivateByteSlice(t *testing.T) {
66	dns.PrivateHandle("ISBN", TypeISBN, NewISBN)
67	defer dns.PrivateHandleRemove(TypeISBN)
68
69	rr, err := dns.NewRR(testrecord)
70	if err != nil {
71		t.Fatal(err)
72	}
73
74	buf := make([]byte, 100)
75	off, err := dns.PackRR(rr, buf, 0, nil, false)
76	if err != nil {
77		t.Errorf("got error packing ISBN: %v", err)
78	}
79
80	custrr := rr.(*dns.PrivateRR)
81	if ln := custrr.Data.Len() + len(custrr.Header().Name) + 11; ln != off {
82		t.Errorf("offset is not matching to length of Private RR: %d!=%d", off, ln)
83	}
84
85	rr1, off1, err := dns.UnpackRR(buf[:off], 0)
86	if err != nil {
87		t.Errorf("got error unpacking ISBN: %v", err)
88		return
89	}
90
91	if off1 != off {
92		t.Errorf("offset after unpacking differs: %d != %d", off1, off)
93	}
94
95	if rr1.String() != testrecord {
96		t.Errorf("record string representation did not match original %#v != %#v", rr1.String(), testrecord)
97	}
98}
99
100const TypeVERSION uint16 = 0xFF01
101
102type VERSION struct {
103	x string
104}
105
106func NewVersion() dns.PrivateRdata { return &VERSION{""} }
107
108func (rd *VERSION) String() string { return rd.x }
109func (rd *VERSION) Parse(txt []string) error {
110	rd.x = strings.TrimSpace(strings.Join(txt, " "))
111	return nil
112}
113
114func (rd *VERSION) Pack(buf []byte) (int, error) {
115	b := []byte(rd.x)
116	n := copy(buf, b)
117	if n != len(b) {
118		return n, dns.ErrBuf
119	}
120	return n, nil
121}
122
123func (rd *VERSION) Unpack(buf []byte) (int, error) {
124	rd.x = string(buf)
125	return len(buf), nil
126}
127
128func (rd *VERSION) Copy(dest dns.PrivateRdata) error {
129	isbn, ok := dest.(*VERSION)
130	if !ok {
131		return dns.ErrRdata
132	}
133	isbn.x = rd.x
134	return nil
135}
136
137func (rd *VERSION) Len() int {
138	return len([]byte(rd.x))
139}
140
141var smallzone = `$ORIGIN example.org.
142@ 3600 IN SOA	sns.dns.icann.org. noc.dns.icann.org. (
143		2014091518 7200 3600 1209600 3600
144)
145    A   1.2.3.4
146ok ISBN 1231-92110-12
147go VERSION (
148	1.3.1 ; comment
149)
150www ISBN 1231-92110-16
151*  CNAME @
152`
153
154func TestPrivateZoneParser(t *testing.T) {
155	dns.PrivateHandle("ISBN", TypeISBN, NewISBN)
156	dns.PrivateHandle("VERSION", TypeVERSION, NewVersion)
157	defer dns.PrivateHandleRemove(TypeISBN)
158	defer dns.PrivateHandleRemove(TypeVERSION)
159
160	r := strings.NewReader(smallzone)
161	z := dns.NewZoneParser(r, ".", "")
162
163	for _, ok := z.Next(); ok; _, ok = z.Next() {
164	}
165	if err := z.Err(); err != nil {
166		t.Fatal(err)
167	}
168}
169