3 use Test
::More tests
=> 8 + 4+6;
9 my $dbh = DBI
->connect('dbi:Pg:db=regano', undef, undef,
10 {AutoCommit
=> 1, RaiseError
=> 1})
11 or BAIL_OUT
$DBI::errstr
;
15 my ($TRUE, $FALSE) = $dbh->selectrow_array(q{SELECT TRUE, FALSE});
19 my $sth = $dbh->prepare
20 (q{WITH open_sessions AS
21 (SELECT s.*, dense_rank() OVER (PARTITION BY s.user_id
22 ORDER BY s.activity DESC)
23 FROM regano.sessions AS s)
24 SELECT s.id, u.username, regano_api.session_check(s.id)
25 FROM open_sessions AS s JOIN regano.users AS u
27 WHERE dense_rank = 1});
29 my ($id, $username, $check);
30 $sth->bind_columns(\
($id, $username, $check));
32 $SESSIONS{$username} = $id if $check;
36 BAIL_OUT
('No sessions in DB') unless scalar keys %SESSIONS;
41 my @CANONICALIZE_TESTS =
42 ( # input, zone, result
43 ['tEsT.TeSt.', 'test.test.', '@'],
44 ['foo.test.test.', 'test.test.', 'foo'],
45 ['Foo.tEst.teSt.', 'test.test.', 'Foo'],
46 ['Foo.example.test.', 'test.test.', 'Foo.example.test.'],
47 ['bar.foo', 'test.test.', 'bar.foo'],
48 ['bar.foo.test.test', 'test.test.', 'bar.foo.test.test'],
49 ['_bar._foo.test.test.', 'test.test.', '_bar._foo'],
50 ['bAr.Foo.TesT.TesT.', 'test.test.', 'bAr.Foo'],
52 my $canonicalize_record_name_st = $dbh->prepare
53 (q{SELECT regano.canonicalize_record_name(?,?)});
55 foreach my $test (@CANONICALIZE_TESTS) {
56 my ($result) = $dbh->selectrow_array
57 ($canonicalize_record_name_st, {}, $test->[0], $test->[1]);
58 is
($result, $test->[2],
59 qq{Canonicalize
'$test->[0]' in zone
'$test->[1]' as
'$test->[2]'});
63 sub update_zone
($$@
) {
64 my $zone_clear_st = $dbh->prepare
65 (q{SELECT regano_api.zone_clear(?,?)});
67 $zone_add_st{SOA
} = $dbh->prepare
68 (q{SELECT regano_api.zone_add_SOA(?,?,?,?,?,?,?,?,?)});
69 $zone_add_st{name
} = $dbh->prepare
70 (q{SELECT regano_api.zone_add_name(?,?,?,?,?,?)});
71 $zone_add_st{text
} = $dbh->prepare
72 (q{SELECT regano_api.zone_add_text(?,?,?,?,?,?)});
73 $zone_add_st{A
} = $dbh->prepare
74 (q{SELECT regano_api.zone_add_A(?,?,?,?,?)});
75 $zone_add_st{AAAA
} = $dbh->prepare
76 (q{SELECT regano_api.zone_add_AAAA(?,?,?,?,?)});
77 $zone_add_st{DS
} = $dbh->prepare
78 (q{SELECT regano_api.zone_add_DS(?,?,?,?,?,?,?,?)});
79 $zone_add_st{MX
} = $dbh->prepare
80 (q{SELECT regano_api.zone_add_MX(?,?,?,?,?,?)});
81 $zone_add_st{SRV
} = $dbh->prepare
82 (q{SELECT regano_api.zone_add_SRV(?,?,?,?,?,?,?,?)});
85 my $zone_name = shift;
89 $zone_clear_st->execute($session, $zone_name);
90 $zone_clear_st->finish;
91 foreach my $rec (@records) {
92 my ($type, @args) = @
$rec;
94 $dbh->selectrow_array($zone_add_st{$type}, {}, $session, $zone_name, @args);
99 sub convert_interval
($) {
100 return $dbh->selectrow_array(qq{SELECT interval
'$_[0]'}) if $_[0];
104 sub translate_zone
($@
) {
105 my $zone_name = shift;
107 my @records_out = ();
108 my $canonicalize_record_name_st = $dbh->prepare
109 (q{SELECT regano.canonicalize_record_name(?,?)});
111 my %data_map = (name
=> 5, text
=> 6,
112 SOA
=> 7, A
=> 8, AAAA
=> 9,
113 DS
=> 10, MX
=> 11, SRV
=> 12);
115 foreach my $rec (@records_in) {
116 my ($type, $ttl, @args) = @
$rec;
118 my @rec = (undef) x
13;
120 if ($type eq 'name' || $type eq 'text') {
121 $rec_type = splice @args, 1, 1;
126 $rec[0] = $type eq 'SOA' ?
0 : $seq_no++;
129 $rec[3] = convert_interval
$ttl;
131 unless ($type eq 'SOA') {
132 $rec[4] = $dbh->selectrow_array($canonicalize_record_name_st, {},
133 shift @args, $zone_name);
134 if (scalar @args > 1) {
135 $rec[$data_map{$type}] = '('.join(',', @args).')';
137 $rec[$data_map{$type}] = $args[0];
141 if ($type eq 'SOA') {
142 my $mname = shift @args;
143 my $hostmaster = shift @args;
145 $rec[$data_map{$type}] = '('.join(',',$mname, $hostmaster,
146 map {convert_interval
$_} @args).')';
147 unshift @records_out, \
@rec;
149 push @records_out, \
@rec;
157 my $get_domain_records_st = $dbh->prepare
158 (q{SELECT seq_no, class, type, ttl, name, data_name, data_text, }.
159 join(', ', map {"data_RR_$_"} qw
/SOA A AAAA DS MX SRV/).
160 q{ FROM regano.domain_records WHERE domain_id = ?});
161 my $get_domain_id_st = $dbh->prepare
162 (q{SELECT id FROM regano.domains
163 WHERE domain_name = ? AND domain_tail = '.test.'});
164 my $get_timestamp_st = $dbh->prepare
165 (q{SELECT EXTRACT(EPOCH FROM regano_api.domain_last_update(?))});
167 my ($domain_id) = $dbh->selectrow_array($get_domain_id_st, {}, 'test');
168 $dbh->selectrow_array(q{SELECT regano_api.zone_clear(?,?)}, {},
169 $SESSIONS{test1
}, 'test.test.');
170 update_zone
$SESSIONS{test1
}, 'test.test.';
171 is_deeply
($dbh->selectall_arrayref($get_domain_records_st, {}, $domain_id),
173 q{Clear records for 'test.test.'});
175 my (@ZONE_IN, @ZONE_OUT);
177 ([SOA
=> undef, 'ns.test.test.', 'hostmaster.test.test.',
178 '12 hours', '5 min', '24 hours', '1 min'],
179 [name
=> undef, 'zone', 'CNAME', 'ns'],
180 [text
=> undef, 'test.test.', 'TXT', 'Sample text'],
181 [A
=> '10 min', 'ns', '1.2.3.4'],
182 [A
=> undef, 'mx', '1.2.3.5'],
183 [AAAA
=> '11 min', 'ns', '::6'],
184 [name
=> undef, 'sub', 'NS', 'ns'],
185 # test data adapted from example in RFC 4034
186 [DS
=> '12 min', 'sub',
187 '60485', '5', '1', '2BB183AF5F22588179A53B0A98631FAD1A292118'],
188 [MX
=> undef, '@', '10', 'mx.test.test.'],
189 # test data adapted from example in RFC 2782
190 [SRV
=> undef, '*._tcp', '0', '0', '0', '.'],
191 [SRV
=> undef, '*._udp', '0', '0', '0', '.'],
193 @ZONE_OUT = translate_zone
'test.test.', @ZONE_IN;
196 ($timestamps{bailiwick_prev
}) = $dbh->selectrow_array
197 ($get_timestamp_st, {}, '.test.');
198 ($timestamps{zone1_prev
}) = $dbh->selectrow_array
199 ($get_timestamp_st, {}, 'test.test.');
201 update_zone
$SESSIONS{test1
}, 'test.test.', @ZONE_IN;
202 is_deeply
($dbh->selectall_arrayref($get_domain_records_st, {}, $domain_id),
204 q{Set records for 'test.test.'});
205 ($timestamps{bailiwick_new
}) = $dbh->selectrow_array
206 ($get_timestamp_st, {}, '.test.');
207 ($timestamps{zone1_new
}) = $dbh->selectrow_array
208 ($get_timestamp_st, {}, 'test.test.');
209 cmp_ok
($timestamps{bailiwick_prev
}, '<', $timestamps{bailiwick_new
},
210 'advance bailiwick timestamp (1)');
211 cmp_ok
($timestamps{zone1_prev
}, '<', $timestamps{zone1_new
},
212 'advance zone timestamp (1)');
213 cmp_ok
($timestamps{bailiwick_new
}, '==', $timestamps{zone1_new
},
214 'new bailiwick timestamp is new zone timestamp (1)');
216 ($domain_id) = $dbh->selectrow_array($get_domain_id_st, {}, 'test-inline');
218 ([A
=> undef, '@', '1.2.3.7'],
219 [AAAA
=> undef, '@', '::8'],
220 [name
=> undef, 'dsub', 'DNAME', 'test-delegated.test.'],
222 @ZONE_OUT = translate_zone
'test-inline.test.', @ZONE_IN;
224 ($timestamps{bailiwick_prev
}) = $dbh->selectrow_array
225 ($get_timestamp_st, {}, '.test.');
226 ($timestamps{zone2_prev
}) = $dbh->selectrow_array
227 ($get_timestamp_st, {}, 'test-inline.test.');
229 update_zone
$SESSIONS{test1
}, 'test-inline.test.', @ZONE_IN;
230 is_deeply
($dbh->selectall_arrayref($get_domain_records_st, {}, $domain_id),
232 q{Set records for 'test-inline.test.'});
233 ($timestamps{bailiwick_new
}) = $dbh->selectrow_array
234 ($get_timestamp_st, {}, '.test.');
235 ($timestamps{zone2_new
}) = $dbh->selectrow_array
236 ($get_timestamp_st, {}, 'test-inline.test.');
237 cmp_ok
($timestamps{bailiwick_prev
}, '<', $timestamps{bailiwick_new
},
238 'advance bailiwick timestamp (2)');
239 cmp_ok
($timestamps{zone2_prev
}, '<', $timestamps{zone2_new
},
240 'advance zone timestamp (2)');
241 cmp_ok
($timestamps{bailiwick_new
}, '==', $timestamps{zone2_new
},
242 'new bailiwick timestamp is new zone timestamp (2)');
244 ($domain_id) = $dbh->selectrow_array($get_domain_id_st, {}, 'test-delegated');
246 ([name
=> undef, '@', 'NS', 'ns'],
247 [A
=> undef, 'ns', '1.2.3.9'],
248 [AAAA
=> undef, 'ns', '::a'],
250 @ZONE_OUT = translate_zone
'test-delegated.test.', @ZONE_IN;
252 update_zone
$SESSIONS{test1
}, 'test-delegated.test.', @ZONE_IN;
253 is_deeply
($dbh->selectall_arrayref($get_domain_records_st, {}, $domain_id),
255 q{Set records for 'test-delegated.test.'});