source: branches/cname-collision/t/cname.t@ 997

Last change on this file since 997 was 997, checked in by Kris Deugau, 5 days ago

/branches/cname-collision

Fix up tests for non-timestamped CNAME colliding with timestamped existing
records to match revised logic tree collision and truth table
See #72

File size: 15.8 KB
Line 
1# -*- Perl -*-
2# Tests for CNAME records
3# Note that not all possible cases are caught!
4# Template records mean not all published records are natively present in the DB
5
6use strict;
7use warnings;
8
9use Test::More;
10use Data::Dumper;
11
12use lib 't';
13
14use DNSTest;
15my $dtest = DNSTest::new;
16
17my ($code,$msg);
18my $rectype = 5;
19my $newname;
20my $newval;
21my $expirystamp;
22my $rcount;
23
24
25## Domain tests
26subtest 'Domain tests' => sub {
27
28 subtest 'CNAME add - new name' => sub {
29 $newname = 'newname.example.com';
30 $newval = 'fredshosting.example.net';
31 ($code, $msg) = $dnsdb->addRec('n', 'n', 1, \$newname, \$rectype, \$newval, 900);
32 ok( $code eq 'OK', "addRec() claimed succeess" );
33 if ($code eq 'OK') {
34 # crosscheck in the DB
35 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 1 AND host = '$newname'");
36 ok( $rcount == 1, " ... [$rcount] yep, hostname only occurs once" );
37 } else {
38 print "not ok: $msg";
39 }
40 };
41
42 subtest 'CNAME add - existing/colliding non-CNAME' => sub {
43 $newname = 'mx1.example.com';
44 ($code, $msg) = $dnsdb->addRec('n', 'n', 1, \$newname, \$rectype, \$newval, 900);
45 ok( $code eq 'FAIL', "addRec() claimed failure" );
46 if ($code eq 'FAIL') {
47 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 1 AND host = '$newname' AND type <> 5");
48 ok( $rcount == 2, " ... [$rcount] record(s) with $newname already exist" );
49 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
50 }
51 };
52
53 subtest 'CNAME add - existing/colliding CNAME' => sub {
54 $newname = 'www.example.com';
55 ($code, $msg) = $dnsdb->addRec('n', 'n', 1, \$newname, \$rectype, \$newval, 900);
56 ok( $code eq 'FAIL', "addRec() claimed failure" );
57 if ($code eq 'FAIL') {
58 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 1 AND host = '$newname' AND type = 5");
59 ok( $rcount == 1, " ... [$rcount] CNAME already exists" );
60 like( $msg, qr/already a CNAME present/, " ... returned matching error" );
61 }
62 };
63
64 subtest 'CNAME update - non-CNAME to CNAME, non-colliding' => sub {
65 $newname = 'smtp.example.com';
66 $newval = 'example.com';
67 ($code, $msg) = $dnsdb->updateRec('n', 'n', 39, 1, \$newname, \$rectype, \$newval, 900);
68 ok( $code eq 'OK', "updateRec() claimed success" );
69 if ($code eq 'OK') {
70 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 1 AND host = '$newname'");
71 ok( $rcount == 1, " ... [$rcount] yep, hostname only occurs once" );
72 } else {
73 print "not ok: $msg";
74 }
75 };
76
77 subtest 'CNAME update - non-CNAME to CNAME, colliding' => sub {
78 $newname = 'mx1.example.com';
79 ($code, $msg) = $dnsdb->updateRec('n', 'n', 39, 1, \$newname, \$rectype, \$newval, 900);
80 ok( $code eq 'FAIL', "updateRec() claimed failure" );
81 if ($code eq 'FAIL') {
82 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 1 AND host = '$newname' AND type <> 5");
83 ok( $rcount == 2, " ... [$rcount] record(s) with $newname already exist" );
84 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
85 }
86 };
87
88 subtest 'CNAME update - name to non-colliding name' => sub {
89 $newname = 'imap.example.com';
90 ($code, $msg) = $dnsdb->updateRec('n', 'n', 37, 1, \$newname, \$rectype, \$newval, 900);
91 ok( $code eq 'OK', "updateRec() claimed success" );
92 if ($code eq 'OK') {
93 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 1 AND host = '$newname'");
94 ok( $rcount == 1, " ... [$rcount] yep, hostname only occurs once" );
95 } else {
96 print "not ok: $msg";
97 }
98 };
99
100 subtest 'CNAME update - name to colliding name' => sub {
101 $newname = 'mx1.example.com';
102 ($code, $msg) = $dnsdb->updateRec('n', 'n', 41, 1, \$newname, \$rectype, \$newval, 900);
103 ok( $code eq 'FAIL', "updateRec() claimed failure" );
104 if ($code eq 'FAIL') {
105 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 1 AND host = '$newname' AND type <> 5");
106 ok( $rcount == 2, " ... [$rcount] record(s) with $newname already exist" );
107 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
108 }
109 };
110
111}; # domain tests
112
113
114## Reverse zone tests
115subtest 'Reverse zone tests' => sub {
116
117 subtest 'CNAME add - new reverse name' => sub {
118 $newval = '192.168.2.12';
119 $newname = '12.8-29.2.168.192.in-addr.arpa';
120 ($code, $msg) = $dnsdb->addRec('n', 'y', 1, \$newname, \$rectype, \$newval, 900);
121 ok( $code eq 'OK', "addRec() claimed succeess" );
122 if ($code eq 'OK') {
123 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = 1 AND val = '$newval'");
124 ok( $rcount == 1, " ... [$rcount] yep, IP only occurs once" );
125 } else {
126 print "not ok: $msg\n";
127 }
128 };
129
130 subtest 'CNAME add - existing/colliding non-CNAME' => sub {
131 $newval = '192.168.2.14';
132 $newname = '14.8-29.2.168.192.in-addr.arpa';
133 ($code, $msg) = $dnsdb->addRec('n', 'y', 1, \$newname, \$rectype, \$newval, 900);
134 ok( $code eq 'FAIL', "addRec() claimed failure" );
135 if ($code eq 'FAIL') {
136 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = 1 AND val = '$newval' AND type <> 5");
137 ok( $rcount == 2, " ... [$rcount] record(s) with $newname already exist" );
138 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
139 }
140 };
141
142 subtest 'CNAME add - existing/colliding CNAME' => sub {
143 $newval = '192.168.2.13';
144 $newname = '13.8-29.2.168.192.in-addr.arpa';
145 ($code, $msg) = $dnsdb->addRec('n', 'y', 1, \$newname, \$rectype, \$newval, 900);
146 ok( $code eq 'FAIL', "addRec() claimed failure" );
147 if ($code eq 'FAIL') {
148 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = 1 AND val = '$newval' AND type = 5");
149 ok( $rcount == 1, " ... [$rcount] CNAME already exists" );
150 like( $msg, qr/already a CNAME present/, " ... returned matching error" );
151 }
152 };
153
154 subtest 'CNAME update - non-CNAME to CNAME, non-colliding' => sub {
155 $newval = '192.168.2.15';
156 $newname = '15-29.arpa.example.net';
157 ($code, $msg) = $dnsdb->updateRec('n', 'y', 43, 1, \$newname, \$rectype, \$newval, 900);
158 ok( $code eq 'OK', "updateRec() claimed success" );
159 if ($code eq 'OK') {
160 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = 1 AND val = '$newval'");
161 ok( $rcount == 1, " ... [$rcount] yep, IP only occurs once" );
162 } else {
163 print "not ok: $msg\n";
164 }
165 };
166
167 subtest 'CNAME update - non-CNAME to CNAME, colliding' => sub {
168 $newval = '192.168.2.14';
169 $newname = 'arpa14.rev.example.net';
170 ($code, $msg) = $dnsdb->updateRec('n', 'y', 42, 1, \$newname, \$rectype, \$newval, 900);
171 ok( $code eq 'FAIL', "updateRec() claimed failure updating revzone record type to CNAME" );
172 if ($code eq 'FAIL') {
173 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = 1 AND val = '$newval' AND type <> 5");
174 ok( $rcount == 2, " ... [$rcount] record(s) with $newval already exist" );
175 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
176 }
177 };
178
179 subtest 'CNAME update - name to non-colliding name' => sub {
180 $newval = '192.168.2.11';
181 ($code, $msg) = $dnsdb->updateRec('n', 'y', 34, 1, \$newname, \$rectype, \$newval, 900);
182 ok( $code eq 'OK', "updateRec() claimed success updating revzone CNAME \"hostname\" (non-colliding)" );
183 if ($code eq 'OK') {
184 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = 1 AND val = '$newval'");
185 ok( $rcount == 1, " ... [$rcount] yep, IP only occurs once" );
186 } else {
187 print "not ok: $msg";
188 }
189 };
190
191 subtest 'CNAME update - name to colliding name' => sub {
192 $newval = '192.168.2.17';
193 ($code, $msg) = $dnsdb->updateRec('n', 'y', 46, 1, \$newname, \$rectype, \$newval, 900);
194 ok( $code eq 'FAIL', "updateRec() claimed failure" );
195 if ($code eq 'FAIL') {
196 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = 1 AND val = '$newval' AND type <> 5");
197 ok( $rcount == 1, " ... [$rcount] record(s) with $newval already exist" );
198 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
199 }
200 };
201
202}; # reverse zone tests
203
204
205## Record expiry/valid-after cases
206subtest 'Record expiry/valid-after' => sub {
207
208 subtest 'CNAME add - nonexpiring' => sub {
209 $newval = 'target.example.com';
210 subtest 'collision with expired record' => sub {
211 $newname = 'expired1.expiry1.test';
212 ($code, $msg) = $dnsdb->addRec('n', 'n', 4, \$newname, \$rectype, \$newval, 900);
213 ok( $code eq 'FAIL', "addRec() claimed failure" );
214 if ($code eq 'FAIL') {
215 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 4 AND host = '$newname'");
216 ok( $rcount == 1, " ... [$rcount] yep, hostname only occurs once" );
217 like( $msg, qr/non-CNAME records with timestamps already exist/, " ... returned matching error" );
218 }
219 };
220# this test arguably overkill, subsumed by earlier test for nonexpiring collision
221 subtest 'collision with soon to expire record' => sub {
222 $newname = 'expired2.expiry1.test';
223 ($code, $msg) = $dnsdb->addRec('n', 'n', 4, \$newname, \$rectype, \$newval, 900);
224 ok( $code eq 'FAIL', "addRec() claimed failure" );
225 if ($code eq 'FAIL') {
226 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 4 AND host = '$newname' AND type <> 5 AND stampactive = 't'");
227 ok( $rcount == 1, " ... [$rcount] record(s) with $newname already exist" );
228# somewhat less overkill if we try to target a unique return based around the expiry bit
229 like( $msg, qr/non-CNAME records with timestamps already exist/, " ... returned matching error" );
230 }
231 };
232 subtest 'collision with pending active-after record' => sub {
233 $newname = 'active-after1.expiry1.test';
234 ($code, $msg) = $dnsdb->addRec('n', 'n', 4, \$newname, \$rectype, \$newval, 900);
235 ok( $code eq 'FAIL', "addRec() claimed success with warning" );
236 if ($code eq 'FAIL') {
237 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 4 AND host = '$newname'");
238 ok( $rcount == 1, " ... [$rcount] correct number of records for $newname" );
239 like( $msg, qr/non-CNAME records with timestamps already exist/, " ... returned matching error" );
240 }
241 };
242 subtest 'collision with active active-after record' => sub {
243 $newname = 'active-after2.expiry1.test';
244 ($code, $msg) = $dnsdb->addRec('n', 'n', 4, \$newname, \$rectype, \$newval, 900);
245 ok( $code eq 'FAIL', "addRec() claimed failure" );
246 if ($code eq 'FAIL') {
247 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 4 AND host = '$newname' AND type <> 5");
248 ok( $rcount == 1, " ... [$rcount] record(s) with $newname already exist" );
249 like( $msg, qr/non-CNAME records with timestamps already exist/, " ... returned matching error" );
250 }
251 };
252 }; # add non-timestamp CNAME
253
254 subtest 'CNAME add - expires soon' => sub {
255 my @ltime = localtime;
256 $expirystamp = sprintf "%i-%i-%i %i:%i", $ltime[5] + 1900, $ltime[4] + 1, $ltime[3] + 3, 15, $ltime[1];
257 $newval = 'target.example.com';
258 subtest 'collision with nonexpiring record' => sub {
259 $newname = 'expires-at1.expiry2.test';
260 ($code, $msg) = $dnsdb->addRec('n', 'n', 5, \$newname, \$rectype, \$newval, 900, undef, 't', $expirystamp);
261 ok($code eq 'FAIL', "addRec() claimed failure");
262 if ($code eq 'FAIL') {
263 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 5 AND host = '$newname'");
264 ok( $rcount == 1, " ... [$rcount] yep, hostname only occurs once" );
265 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
266 }
267 };
268 subtest 'collision with expiring record' => sub {
269 $newname = 'expires-at2.expiry2.test';
270 ($code, $msg) = $dnsdb->addRec('n', 'n', 5, \$newname, \$rectype, \$newval, 900, undef, 't', $expirystamp);
271 ok( $code eq 'FAIL', "addRec() claimed failure");
272 if ($code eq 'FAIL') {
273 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 5 AND host = '$newname' AND type <> 5");
274 ok( $rcount == 1, " ... [$rcount] record(s) with $newname already exist" );
275 like( $msg, qr/One or more non-CNAME records/, " ... returned matching error" );
276 }
277 };
278 subtest 'expire before valid-after record' => sub {
279 $newname = 'expires-at3.expiry2.test';
280 ($code, $msg) = $dnsdb->addRec('n', 'n', 5, \$newname, \$rectype, \$newval, 900, undef, 't', $expirystamp);
281 ok( $code eq 'OK', "addRec() claimed success" );
282 if ($code eq 'OK') {
283 # crosscheck in the DB
284 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 5 AND host = '$newname'");
285 ok( $rcount == 2, " ... [$rcount] correct number of records for $newname" );
286 my ($newstamp) = $dbh->selectrow_array("SELECT extract(epoch from stamp) FROM records WHERE domain_id = 5 AND host = '$newname' ".
287 "AND stampactive = 't' AND expires = 't'");
288 my ($oldstamp) = $dbh->selectrow_array("SELECT extract(epoch from stamp) FROM records WHERE domain_id = 5 AND host = '$newname' ".
289 "AND stampactive = 't' AND expires = 'f'");
290 ok( $newstamp <= $oldstamp, " ... added record expires before existing active-after record goes active" );
291 } else {
292 print "not ok: $msg";
293 }
294 };
295 subtest 'expire after valid-after record' => sub {
296 $newname = 'expires-at4.expiry2.test';
297 ($code, $msg) = $dnsdb->addRec('n', 'n', 5, \$newname, \$rectype, \$newval, 900, undef, 't', $expirystamp);
298 ok( $code eq 'WARN', "addRec() claimed success with warning" );
299 if ($code eq 'WARN') {
300 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 5 AND host = '$newname'");
301 ok( $rcount == 2, " ... [$rcount] correct number of records for $newname" );
302 like( $msg, qr/added with modified expiry time; conflicting valid-after record found/, " ... returned appropriate warning message" );
303 my ($newstamp) = $dbh->selectrow_array("SELECT stamp FROM records WHERE domain_id = 5 AND host = '$newname' ".
304 "AND stampactive = 't' AND expires = 't'");
305 my ($oldstamp) = $dbh->selectrow_array("SELECT stamp FROM records WHERE domain_id = 5 AND host = '$newname' ".
306 "AND stampactive = 't' AND expires = 'f'");
307 ok( $newstamp eq $oldstamp, " ... coerced timestamp matches existing active-after timestamp" );
308 } else {
309 print "not ok: $msg";
310 }
311 };
312 subtest 'collision with expired record' => sub {
313 $newname = 'expires-at5.expiry2.test';
314 ($code, $msg) = $dnsdb->addRec('n', 'n', 5, \$newname, \$rectype, \$newval, 900, undef, 't', $expirystamp);
315 ok( $code eq 'OK', "addRec() claimed success" );
316 if ($code eq 'OK') {
317 # crosscheck in the DB
318 ($rcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE domain_id = 5 AND host = '$newname'");
319 ok( $rcount == 2, " ... [$rcount] correct number of records for $newname" );
320 my ($newstamp) = $dbh->selectrow_array("SELECT extract(epoch from stamp) FROM records WHERE domain_id = 5 AND host = '$newname' ".
321 "AND stampactive = 't' AND expires = 't' AND stamp >= now()");
322 my ($oldstamp) = $dbh->selectrow_array("SELECT extract(epoch from stamp) FROM records WHERE domain_id = 5 AND host = '$newname' ".
323 "AND stampactive = 't' AND expires = 't' AND stamp <= now()");
324 ok( $newstamp > $oldstamp, " ... added record expires after existing, already-expired record" );
325 } else {
326 print "not ok: $msg";
327 }
328 };
329 }; # add expiring CNAME
330
331}; # record expiry/valid-after
332
333
334done_testing();
Note: See TracBrowser for help on using the repository browser.