10 # neither LibMagic nor MMagic tell them apart
15 $HAVE->{$package} = eval qq{ require $package; };
20 use File::Basename qw(dirname);
21 use File::Copy qw(cp);
22 use File::Path qw(mkpath rmtree);
23 use File::Rsync::Mirror::Recent;
24 use File::Rsync::Mirror::Recentfile;
25 use List::MoreUtils qw(uniq);
27 use Time::HiRes qw(time sleep);
30 my $root_from = "t/ta";
32 rmtree [$root_from, $root_to];
43 $tests += @serializers;
44 if ($HAVE->{"File::LibMagic"}||$HAVE->{"File::MMagic"}) {
45 $tests += @serializers;
49 my $ttt = "$root_from/ttt";
50 open my $fh, ">", $ttt or die "Could not open: $!";
52 close $fh or die "Could not close: $!";
54 if ($HAVE->{"File::LibMagic"}) {
55 $fm = File::LibMagic->new();
56 } elsif ($HAVE->{"File::MMagic"}) {
57 $fm = File::MMagic->new();
59 for my $s (@serializers) {
60 my $rf = File::Rsync::Mirror::Recentfile->new
62 filenameroot => "RECENT",
64 localroot => $root_from,
65 serializer_suffix => $s,
67 $rf->update($ttt,"new");
69 my $magic = $fm->checktype_filename("$root_from/RECENT-1m$s");
71 ("Got a magic[%s] for s[%s]: [%s]",
77 my $content = do {open my $fh, "$root_from/RECENT-1m$s";local $/;<$fh>};
78 $content = Dumpvalue->new()->stringify($content);
79 my $want_length = 42; # or maybe 3 more
80 substr($content,$want_length) = "..." if length $content > 3+$want_length;
81 ok($content, "Got a substr for s[$s]: [$content]");
85 rmtree [$root_from, $root_to];
88 # very small tree, aggregate it
92 @intervals = qw( 2s 4s 8s 16s 32s Z );
94 ok(1, "starting smalltree block");
95 is 6, scalar @intervals, "array has 6 elements: @intervals";
96 my $rf0 = File::Rsync::Mirror::Recentfile->new
98 aggregator => [@intervals[1..$#intervals]],
99 interval => $intervals[0],
100 localroot => $root_from,
108 for my $iv (@intervals) {
117 mkpath dirname $file;
118 open my $fh, ">", $file or die "Could not open '$file': $!";
119 print $fh time, ":", $file, "\n";
120 close $fh or die "Could not close '$file': $!";
121 $rf0->update($file,"new");
124 my $recent_events = $rf0->recent_events;
125 # faking internals as if the contents were wide-spread in time
126 for my $evi (0..$#$recent_events) {
127 my $ev = $recent_events->[$evi];
128 $ev->{epoch} -= 2**($evi*.25);
130 $rf0->write_recent($recent_events);
132 my $filesize_threshold = 1750; # XXX may be system dependent
133 for my $iv (@intervals) {
134 my $rf = "$root_from/RECENT-$iv.yaml";
135 my $filesize = -s $rf;
136 # now they have $filesize_threshold+ bytes because they were merged for the
137 # first time ever and could not be truncated for this reason.
138 ok($filesize_threshold < $filesize, "file $iv has good size[$filesize]");
139 utime 0, 0, $rf; # so that the next aggregate isn't skipped
141 open my $fh, ">", "$root_from/finissage" or die "Could not open: $!";
143 close $fh or die "Could not close: $!";
144 $rf0->update("$root_from/finissage","new");
145 $rf0 = File::Rsync::Mirror::Recentfile->new_from_file("$root_from/RECENT-2s.yaml");
147 for my $iv (@intervals) {
148 my $filesize = -s "$root_from/RECENT-$iv.yaml";
149 # now they have <$filesize_threshold bytes because the second aggregate could
151 ok($iv eq "Z" || $filesize_threshold > $filesize, "file $iv has good size[$filesize]");
153 my $dagg1 = $rf0->_debug_aggregate;
154 Time::HiRes::sleep 1.2;
155 $rf0->aggregate; # should not change the file
156 my $dagg2 = $rf0->_debug_aggregate;
157 is $dagg2->[0]{mtime}, $dagg1->[0]{mtime}, "no change by gratuitous aggregate";
159 my $recc = File::Rsync::Mirror::Recent->new
161 local => "$root_from/RECENT-2s.yaml",
163 ok $recc->overview, "overview created";
167 rmtree [$root_from, $root_to];
170 # replay a short history, run aggregate on it, add files, aggregate again
171 BEGIN { $tests += 208 }
172 ok(1, "starting short history block");
173 my $rf = File::Rsync::Mirror::Recentfile->new_from_file("t/RECENT-6h.yaml");
174 my $recent_events = $rf->recent_events;
175 my $recent_events_cnt = scalar @$recent_events;
179 "found $recent_events_cnt events",
182 $rf->localroot($root_from);
183 $rf->comment("produced during the test 02-operation.t");
184 $rf->aggregator([qw(10s 30s 1m 1h Z)]);
186 my $start = Time::HiRes::time;
187 for my $e (@$recent_events) {
192 $pass==0 ? $root_from : $root_to,
195 mkpath dirname $file;
196 open my $fh, ">", $file or die "Could not open '$file': $!";
197 print $fh time, ":", $file, "\n";
198 close $fh or die "Could not close '$file': $!";
200 $rf->update($file,$e->{type});
205 my $took = Time::HiRes::time - $start;
206 ok $took > 0, "creating the tree and aggregate took $took seconds";
207 my $dagg1 = $rf->_debug_aggregate;
209 my $file_from = "$root_from/anotherfilefromtesting$i";
210 open my $fh, ">", $file_from or die "Could not open: $!";
211 print $fh time, ":", $file_from;
212 close $fh or die "Could not close: $!";
213 $rf->update($file_from,"new");
216 my $dagg2 = $rf->_debug_aggregate;
219 ok($dagg1->[0]{size} < $dagg2->[0]{size}, "The second 5s file size larger: $dagg1->[0]{size} < $dagg2->[0]{size}");
220 ok($dagg1->[1]{mtime} <= $dagg2->[1]{mtime}, "The second 30s file timestamp larger: $dagg1->[1]{mtime} <= $dagg2->[1]{mtime}");
221 is $dagg1->[2]{size}, $dagg2->[2]{size}, "The 1m file size unchanged";
222 is $dagg1->[3]{mtime}, $dagg2->[3]{mtime}, "The 1h file timestamp unchanged";
223 ok -l "t/ta/RECENT.recent", "found the symlink";
224 my $have_slept = my $have_worked = 0;
225 $start = Time::HiRes::time;
232 ($i<25) ? ($i%12) : $i,
234 open my $fh, ">", $file or die "Could not open '$file': $!";
235 print $fh time, ":", $file, "\n";
236 close $fh or die "Could not close '$file': $!";
237 my $another_rf = File::Rsync::Mirror::Recentfile->new
240 localroot => $root_from,
241 aggregator => [qw(10s 30s 1m 1h Z)],
243 $another_rf->update($file,"new");
244 my $should_have = 97 + (($i<25) ? ($i < 12 ? ($i+1) : 12) : ($i-12));
245 my($news,$filtered_news);
247 $another_rf->aggregate;
250 my $recc = File::Rsync::Mirror::Recent->new
252 local => "$root_from/RECENT-5s.yaml",
254 $news = $recc->news ();
255 $filtered_news = [ uniq map { $_->{path} } @$news ];
257 is scalar @$filtered_news, $should_have, "should_have[$should_have]" or die;
258 $debug->[$i] = $news;
259 my $rf2 = File::Rsync::Mirror::Recentfile->new_from_file("$root_from/RECENT-5s.yaml");
260 my $rece = $rf2->recent_events;
261 my $rececnt = @$rece;
262 my $span = $rece->[0]{epoch} - $rece->[-1]{epoch};
263 $have_worked = Time::HiRes::time - $start - $have_slept;
265 && ($i<50 ? $span <= 5 # we have run aggregate, so it guaranteed(*)
266 : $i < 90 ? 1 # we have not yet spent 5 seconds, so cannot predict
267 : $span > 5 # we have certainly written enough files now, must happen
270 ("i[%s]cnt[%s]span[%s]worked[%6.4f]",
276 $have_slept += Time::HiRes::sleep 0.2;
278 # (*) "<=" instead of "<" because of rounding errors
283 BEGIN { $tests += 2 }
284 my $rf = File::Rsync::Mirror::Recentfile->new
286 filenameroot => "RECENT",
288 localroot => $root_to,
289 max_rsync_errors => 0,
290 remote_dir => $root_from,
296 # not available in rsync 3.0.3: 'omit-dir-times' => 1,
304 $success = $rf->mirror;
305 my $re = $rf->recent_events;
306 $somefile_epoch = $re->[24]{epoch};
307 } elsif (1 == $pass) {
308 $success = $rf->mirror(after => $somefile_epoch);
310 ok($success, "mirrored without dying");
313 my $recc = File::Rsync::Mirror::Recent->new
314 ( # ($root_from, $root_to)
315 local => "$root_from/RECENT-5s.yaml",
317 # diag $recc->overview;
320 my $recc = File::Rsync::Mirror::Recent->new
321 ( # ($root_from, $root_to)
322 local => "$root_to/RECENT-30s.yaml",
324 # diag $recc->overview;
328 rmtree [$root_from, $root_to];
330 BEGIN { plan tests => $tests }
334 # cperl-indent-level: 4