1#!/usr/bin/perl 2 3use strict; 4use warnings; 5 6# 7# Unit tests for heap implementation 8# 9# Test the following methods: 10# new 11# is_empty 12# empty 13# insert 14# remove 15# popheap 16# promote 17# lookup 18# set_val 19# rekey 20# expire_order 21 22 23# Finish these later. 24 25# They're nonurgent because the important heap stuff is extensively 26# tested by tests 19, 20, 24, 30, 32, 33, and 40, as well as by pretty 27# much everything else. 28print "1..1\n"; 29 30 31my ($N, @R, $Q, $ar) = (1); 32 33use Tie::File; 34print "ok $N\n"; 35$N++; 36exit; 37 38__END__ 39 40my @HEAP_MOVE; 41sub Fake::Cache::_heap_move { push @HEAP_MOVE, @_ } 42 43my $h = Tie::File::Heap->new(bless [] => 'Fake::Cache'); 44print "ok $N\n"; 45$N++; 46 47# (3) Are all the methods there? 48{ 49 my $good = 1; 50 for my $meth (qw(new is_empty empty lookup insert remove popheap 51 promote set_val rekey expire_order)) { 52 unless ($h->can($meth)) { 53 print STDERR "# Method '$meth' is missing.\n"; 54 $good = 0; 55 } 56 } 57 print $good ? "ok $N\n" : "not ok $N\n"; 58 $N++; 59} 60 61# (4) Straight insert and removal FIFO test 62$ar = 'a0'; 63for (1..10) { 64 $h->insert($_, $ar++); 65} 66for (1..10) { 67 push @R, $h->popheap; 68} 69$iota = iota('a',9); 70print "@R" eq $iota 71 ? "ok $N\n" : "not ok $N \# expected ($iota), got (@R)\n"; 72$N++; 73 74# (5) Remove from empty heap 75$n = $h->popheap; 76print ! defined $n ? "ok $N\n" : "not ok $N \# expected UNDEF, got $n"; 77$N++; 78 79# (6) Interleaved insert and removal 80$Q = 0; 81@R = (); 82for my $i (1..4) { 83 for my $j (1..$i) { 84 $h->insert($Q, "b$Q"); 85 $Q++; 86 } 87 for my $j (1..$i) { 88 push @R, $h->popheap; 89 } 90} 91$iota = iota('b', 9); 92print "@R" eq $iota ? "ok $N\n" : "not ok $N \# expected ($iota), got (@R)\n"; 93$N++; 94 95# (7) It should be empty now 96print $h->is_empty ? "ok $N\n" : "not ok $N\n"; 97$N++; 98 99# (8) Insert and delete 100$Q = 1; 101for (1..10) { 102 $h->insert($_, "c$Q"); 103 $Q++; 104} 105for (2, 4, 6, 8, 10) { 106 $h->remove($_); 107} 108@R = (); 109push @R, $n while defined ($n = $h->popheap); 110print "@R" eq "c1 c3 c5 c7 c9" ? 111 "ok $N\n" : "not ok $N \# expected (c1 c3 c5 c7 c9), got (@R)\n"; 112$N++; 113 114# (9) Interleaved insert and delete 115$Q = 1; my $QQ = 1; 116@R = (); 117for my $i (1..4) { 118 for my $j (1..$i) { 119 $h->insert($Q, "d$Q"); 120 $Q++; 121 } 122 for my $j (1..$i) { 123 $h->remove($QQ) if $QQ % 2 == 0; 124 $QQ++; 125 } 126} 127push @R, $n while defined ($n = $h->popheap); 128print "@R" eq "d1 d3 d5 d7 d9" ? 129 "ok $N\n" : "not ok $N \# expected (d1 d3 d5 d7 d9), got (@R)\n"; 130$N++; 131 132# (10) Promote 133$Q = 1; 134for (1..10) { 135 $h->insert($_, "e$Q"); 136 $Q++; 137} 138for (2, 4, 6, 8, 10) { 139 $h->promote($_); 140} 141@R = (); 142push @R, $n while defined ($n = $h->popheap); 143print "@R" eq "e1 e3 e5 e7 e9 e2 e4 e6 e8 e10" ? 144 "ok $N\n" : 145 "not ok $N \# expected (e1 e3 e5 e7 e9 e2 e4 e6 e8 e10), got (@R)\n"; 146$N++; 147 148# (11-15) Lookup 149$Q = 1; 150for (1..10) { 151 $h->insert($_, "f$Q"); 152 $Q++; 153} 154for (2, 4, 6, 4, 8) { 155 my $r = $h->lookup($_); 156 print $r eq "f$_" ? "ok $N\n" : "not ok $N \# expected f$_, got $r\n"; 157 $N++; 158} 159 160# (16) It shouldn't be empty 161print ! $h->is_empty ? "ok $N\n" : "not ok $N\n"; 162$N++; 163 164# (17) Lookup should have promoted the looked-up records 165@R = (); 166push @R, $n while defined ($n = $h->popheap); 167print "@R" eq "f1 f3 f5 f7 f9 f10 f2 f6 f4 f8" ? 168 "ok $N\n" : 169 "not ok $N \# expected (f1 f3 f5 f7 f9 f10 f2 f6 f4 f8), got (@R)\n"; 170$N++; 171 172# (18-19) Typical 'rekey' operation 173$Q = 1; 174for (1..10) { 175 $h->insert($_, "g$Q"); 176 $Q++; 177} 178 179$h->rekey([6,7,8,9,10], [8,9,10,11,12]); 180my %x = qw(1 g1 2 g2 3 g3 4 g4 5 g5 181 8 g6 9 g7 10 g8 11 g9 12 g10); 182{ 183 my $good = 1; 184 for my $k (keys %x) { 185 my $v = $h->lookup($k); 186 $v = "UNDEF" unless defined $v; 187 unless ($v eq $x{$k}) { 188 print "# looked up $k, got $v, expected $x{$k}\n"; 189 $good = 0; 190 } 191 } 192 print $good ? "ok $N\n" : "not ok $N\n"; 193 $N++; 194} 195{ 196 my $good = 1; 197 for my $k (6, 7) { 198 my $v = $h->lookup($k); 199 if (defined $v) { 200 print "# looked up $k, got $v, should have been undef\n"; 201 $good = 0; 202 } 203 } 204 print $good ? "ok $N\n" : "not ok $N\n"; 205 $N++; 206} 207 208# (20) keys 209@R = sort { $a <=> $b } $h->keys; 210print "@R" eq "1 2 3 4 5 8 9 10 11 12" ? 211 "ok $N\n" : 212 "not ok $N \# expected (1 2 3 4 5 8 9 10 11 12) got (@R)\n"; 213$N++; 214 215# (21) update 216for (1..5, 8..12) { 217 $h->update($_, "h$_"); 218} 219@R = (); 220for (sort { $a <=> $b } $h->keys) { 221 push @R, $h->lookup($_); 222} 223print "@R" eq "h1 h2 h3 h4 h5 h8 h9 h10 h11 h12" ? 224 "ok $N\n" : 225 "not ok $N \# expected (h1 h2 h3 h4 h5 h8 h9 h10 h11 h12) got (@R)\n"; 226$N++; 227 228# (22-23) bytes 229my $B; 230$B = $h->bytes; 231print $B == 23 ? "ok $N\n" : "not ok $N \# expected 23, got $B\n"; 232$N++; 233$h->update('12', "yobgorgle"); 234$B = $h->bytes; 235print $B == 29 ? "ok $N\n" : "not ok $N \# expected 29, got $B\n"; 236$N++; 237 238# (24-25) empty 239$h->empty; 240print $h->is_empty ? "ok $N\n" : "not ok $N\n"; 241$N++; 242$n = $h->popheap; 243print ! defined $n ? "ok $N\n" : "not ok $N \# expected UNDEF, got $n"; 244$N++; 245 246# (26) very weak testing of DESTROY 247undef $h; 248# are we still alive? 249print "ok $N\n"; 250$N++; 251 252 253sub iota { 254 my ($p, $n) = @_; 255 my $r; 256 my $i = 0; 257 while ($i <= $n) { 258 $r .= "$p$i "; 259 $i++; 260 } 261 chop $r; 262 $r; 263} 264