12 $Opt{verbose} ||= $ENV{PERL_RERSYNCRECENT_TEST_VERBOSE};
16 # neither LibMagic nor MMagic tell them apart
21 $HAVE->{$package} = eval qq{ require $package; };
26 use File::Basename qw(dirname);
27 use File::Copy qw(cp);
28 use File::Path qw(mkpath rmtree);
29 use File::Rsync::Mirror::Recent;
30 use File::Rsync::Mirror::Recentfile;
31 use List::MoreUtils qw(uniq);
33 use Time::HiRes qw(time sleep);
36 my $root_from = "t/ta";
38 my $statusfile = "t/recent-rmirror-state.yml";
39 rmtree [$root_from, $root_to];
50 $tests += @serializers;
51 if ($HAVE->{"File::LibMagic"}||$HAVE->{"File::MMagic"}) {
52 $tests += @serializers;
56 my $ttt = "$root_from/ttt";
57 open my $fh, ">", $ttt or die "Could not open: $!";
59 close $fh or die "Could not close: $!";
61 if ($HAVE->{"File::LibMagic"}) {
62 $fm = File::LibMagic->new();
63 } elsif ($HAVE->{"File::MMagic"}) {
64 $fm = File::MMagic->new();
66 for my $s (@serializers) {
67 my $rf = File::Rsync::Mirror::Recentfile->new
69 filenameroot => "RECENT",
71 localroot => $root_from,
72 serializer_suffix => $s,
74 $rf->update($ttt,"new");
76 my $magic = $fm->checktype_filename("$root_from/RECENT-1m$s");
78 ("Got a magic[%s] for s[%s]: [%s]",
84 my $content = do {open my $fh, "$root_from/RECENT-1m$s";local $/;<$fh>};
85 $content = Dumpvalue->new()->stringify($content);
86 my $want_length = 42; # or maybe 3 more
87 substr($content,$want_length) = "..." if length $content > 3+$want_length;
88 ok($content, "Got a substr for s[$s]: [$content]");
92 rmtree [$root_from, $root_to];
95 # very small tree, aggregate it
99 @intervals = qw( 2s 4s 8s 16s 32s Z );
101 ok(1, "starting smalltree block");
102 is 6, scalar @intervals, "array has 6 elements: @intervals";
104 my $rf0 = File::Rsync::Mirror::Recentfile->new
106 aggregator => [@intervals[1..$#intervals]],
107 interval => $intervals[0],
108 localroot => $root_from,
116 my $timestampfutured = 0;
117 for my $iv (@intervals) {
126 mkpath dirname $file;
127 open my $fh, ">", $file or die "Could not open '$file': $!";
128 print $fh time, ":", $file, "\n";
129 close $fh or die "Could not close '$file': $!";
130 $rf0->update($file,"new");
131 if ($pass==1 && !$timestampfutured) {
133 my $recent_events = $rf0->recent_events;
134 $recent_events->[0]{epoch} += 987654321;
135 $rf0->write_recent($recent_events);
140 my $recent_events = $rf0->recent_events;
141 # faking internals as if the contents were wide-spread in time
142 for my $evi (0..$#$recent_events) {
143 my $ev = $recent_events->[$evi];
144 $ev->{epoch} -= 2**($evi*.25);
146 $rf0->write_recent($recent_events);
148 my $filesize_threshold = 1750; # XXX may be system dependent
150 for my $iv (@intervals) {
151 my $rf = "$root_from/RECENT-$iv.yaml";
152 my $filesize = -s $rf;
153 $size_before{$iv} = $filesize;
154 # now they have $filesize_threshold+ bytes because they were merged for the
155 # first time ever and could not be truncated for this reason.
156 ok( $filesize > $filesize_threshold, "file $iv (before merging) has good size[$filesize]");
157 utime 0, 0, $rf; # so that the next aggregate isn't skipped
159 open my $fh, ">", "$root_from/finissage" or die "Could not open: $!";
161 close $fh or die "Could not close: $!";
162 $rf0->update("$root_from/finissage","new");
163 $rf0 = File::Rsync::Mirror::Recentfile->new_from_file("$root_from/RECENT-2s.yaml");
165 for my $iv (@intervals) {
166 my $filesize = -s "$root_from/RECENT-$iv.yaml";
167 # now they have <$filesize_threshold bytes because the second aggregate could
169 ok($iv eq "Z" || $filesize<$size_before{$iv}, "file $iv (after merging) has good size[$filesize]");
171 my $dagg1 = $rf0->_debug_aggregate;
172 Time::HiRes::sleep 1.2;
173 $rf0->aggregate; # should not change the file
174 my $dagg2 = $rf0->_debug_aggregate;
175 is $dagg2->[0]{mtime}, $dagg1->[0]{mtime}, "no change by gratuitous aggregate";
177 my $recc = File::Rsync::Mirror::Recent->new
179 local => "$root_from/RECENT-2s.yaml",
181 ok $recc->overview, "overview created";
182 # diag $recc->overview;
184 rmtree [$root_from, $root_to];
188 rmtree [$root_from, $root_to];
191 # replay a short history, run aggregate on it, add files, aggregate again
192 BEGIN { $tests += 208 }
193 ok(1, "starting short history block");
194 my $rf = File::Rsync::Mirror::Recentfile->new_from_file("t/RECENT-6h.yaml");
195 my $recent_events = $rf->recent_events;
196 my $recent_events_cnt = scalar @$recent_events;
200 "found $recent_events_cnt events",
203 $rf->localroot($root_from);
204 $rf->comment("produced during the test 02-operation.t");
205 $rf->aggregator([qw(10s 30s 1m 1h Z)]);
207 my $start = Time::HiRes::time;
208 for my $e (@$recent_events) {
213 $pass==0 ? $root_from : $root_to,
216 mkpath dirname $file;
217 open my $fh, ">", $file or die "Could not open '$file': $!";
218 print $fh time, ":", $file, "\n";
219 close $fh or die "Could not close '$file': $!";
221 $rf->update($file,$e->{type});
226 my $took = Time::HiRes::time - $start;
227 ok $took > 0, "creating the tree and aggregate took $took seconds";
228 my $dagg1 = $rf->_debug_aggregate;
230 my $file_from = "$root_from/anotherfilefromtesting$i";
231 open my $fh, ">", $file_from or die "Could not open: $!";
232 print $fh time, ":", $file_from;
233 close $fh or die "Could not close: $!";
234 $rf->update($file_from,"new");
237 my $dagg2 = $rf->_debug_aggregate;
239 ok($dagg1->[0]{size} < $dagg2->[0]{size}, "The second 5s file size larger: $dagg1->[0]{size} < $dagg2->[0]{size}");
240 ok($dagg1->[1]{mtime} <= $dagg2->[1]{mtime}, "The second 30s file timestamp larger: $dagg1->[1]{mtime} <= $dagg2->[1]{mtime}");
241 is $dagg1->[2]{size}, $dagg2->[2]{size}, "The 1m file size unchanged";
242 is $dagg1->[3]{mtime}, $dagg2->[3]{mtime}, "The 1h file timestamp unchanged";
243 ok -l "t/ta/RECENT.recent", "found the symlink";
244 my $have_slept = my $have_worked = 0;
245 $start = Time::HiRes::time;
252 ($i<25) ? ($i%12) : $i,
254 open my $fh, ">", $file or die "Could not open '$file': $!";
255 print $fh time, ":", $file, "\n";
256 close $fh or die "Could not close '$file': $!";
257 my $another_rf = File::Rsync::Mirror::Recentfile->new
260 localroot => $root_from,
261 aggregator => [qw(10s 30s 1m 1h Z)],
263 $another_rf->update($file,"new");
264 my $should_have = 97 + (($i<25) ? ($i < 12 ? ($i+1) : 12) : ($i-12));
265 my($news,$filtered_news);
267 $another_rf->aggregate;
270 my $recc = File::Rsync::Mirror::Recent->new
272 local => "$root_from/RECENT-5s.yaml",
274 $news = $recc->news ();
275 $filtered_news = [ uniq map { $_->{path} } @$news ];
277 is scalar @$filtered_news, $should_have, "should_have[$should_have]" or die;
278 $debug->[$i] = $news;
279 my $rf2 = File::Rsync::Mirror::Recentfile->new_from_file("$root_from/RECENT-5s.yaml");
280 my $rece = $rf2->recent_events;
281 my $rececnt = @$rece;
282 my $span = $rece->[0]{epoch} - $rece->[-1]{epoch};
283 $have_worked = Time::HiRes::time - $start - $have_slept;
285 && ($i<50 ? $span <= 5 # we have run aggregate, so it guaranteed(*)
286 : $i < 90 ? 1 # we have not yet spent 5 seconds, so cannot predict
287 : $span > 5 # we have certainly written enough files now, must happen
290 ("i[%s]cnt[%s]span[%s]worked[%6.4f]",
296 $have_slept += Time::HiRes::sleep 0.2;
298 # (*) "<=" instead of "<" because of rounding errors
303 BEGIN { $tests += 2 }
304 my $rf = File::Rsync::Mirror::Recentfile->new
306 filenameroot => "RECENT",
308 localroot => $root_to,
309 max_rsync_errors => 0,
310 remote_dir => $root_from,
316 # not available in rsync 3.0.3: 'omit-dir-times' => 1,
324 $success = $rf->mirror;
325 my $re = $rf->recent_events;
326 $somefile_epoch = $re->[24]{epoch};
327 } elsif (1 == $pass) {
328 $success = $rf->mirror(after => $somefile_epoch);
330 ok($success, "mirrored pass[$pass] without dying");
333 my $recc = File::Rsync::Mirror::Recent->new
334 ( # ($root_from, $root_to)
335 local => "$root_from/RECENT-5s.yaml",
338 diag $recc->overview;
341 my $recc = File::Rsync::Mirror::Recent->new
343 # ignore_link_stat_errors => 1,
344 localroot => $root_to,
345 remote => "$root_from/RECENT-5s.yaml",
357 my $recc = File::Rsync::Mirror::Recent->new
358 ( # ($root_from, $root_to)
359 local => "$root_from/RECENT-5s.yaml",
362 diag $recc->overview;
365 my $recc = File::Rsync::Mirror::Recent->new
367 # ignore_link_stat_errors => 1,
368 localroot => $root_to,
369 remote => "$root_from/RECENT.recent",
370 verbose => $Opt{verbose},
377 _runstatusfile => $statusfile,
380 my $rf2 = File::Rsync::Mirror::Recentfile->new_from_file("$root_from/RECENT-5s.yaml");
381 my $file = "$root_from/about-re-mirroring.txt";
382 open my $fh, ">", $file or die "Could not open '$file': $!";
384 close $fh or die "Could not close '$file': $!";
385 $rf2->update($file, "new");
390 rmtree [$root_from, $root_to, $statusfile] unless $Opt{verbose};
392 BEGIN { plan tests => $tests }
396 # cperl-indent-level: 4