fsck: log bad count correctly instead of policy violation
[MogileFS-Server.git] / t / multiple-hosts-replpol.t
blob404fbd2a014e32418076620b927d3e9ca2cef34c
1 #!/usr/bin/perl
3 use strict;
4 use warnings;
5 use Test::More;
6 use FindBin qw($Bin);
8 use MogileFS::Server;
9 use MogileFS::Util qw(error_code);
10 use MogileFS::ReplicationPolicy::MultipleHosts;
11 use MogileFS::Test;
13 plan tests => 13;
15 # already good.
16 is(rr("min=2 h1[d1=X d2=_] h2[d3=X d4=_]"),
17 "all_good", "all good");
19 # need to get it onto host2...
20 is(rr("min=2 h1[d1=X d2=_] h2[d3=_ d4=_]"),
21 "ideal(3,4)", "need host2");
23 # still needs to be on host2, even though 2 copies on host1
24 is(rr("min=2 h1[d1=X d2=X] h2[d3=_ d4=_]"),
25 "ideal(3,4)", "need host2, even though 2 on host1");
27 # anywhere will do. (can happen on, say, rebalance)
28 is(rr("min=2 h1[d1=_ d2=_] h2[d3=_ d4=_]"),
29 "ideal(1,2,3,4)", "anywhere");
31 # should desperately try d2, since host2 is down
32 is(rr("min=2 h1[d1=X d2=_] h2=down[d3=_ d4=_]"),
33 "desperate(2)");
35 # should try host3, since host2 is down
36 is(rr("min=2 h1[d1=X d2=_] h2=down[d3=_ d4=_] h3[d5=_ d6=_]"),
37 "ideal(5,6)");
39 # need a copy on a non-dead disk on host1
40 is(rr("min=2 h1[d1=_ d2=X,dead] h2=alive[d3=X d4=_]"),
41 "ideal(1)");
43 # this is an ideal move, since we only have 2 unique hosts:
44 is(rr("min=3 h1[d1=_ d2=X] h2[d3=X d4=_]"),
45 "ideal(1,4)");
47 # ... but if we have a 3rd host, it's gotta be there
48 is(rr("min=3 h1[d1=_ d2=X] h2[d3=X d4=_] h3[d5=_]"),
49 "ideal(5)");
51 # ... unless that host is down, in which case it's back to 1/4,
52 # but desperately
53 is(rr("min=3 h1[d1=_ d2=X] h2[d3=X d4=_] h3=down[d5=_]"),
54 "desperate(1,4)");
56 # too good, uniq hosts > min
57 is(rr("min=2 h1[d1=X d2=_] h2[d3=X d4=_] h3[d5=X]"),
58 "too_good");
60 # too good, but but with uniq hosts == min
61 is(rr("min=2 h1[d1=X d2=X] h2[d3=X d4=_]"),
62 "too_good");
64 # be happy with 3 copies, even though two are on same host (that's our max unique hosts)
65 is(rr("min=3 h1[d1=_ d2=X] h2[d3=X d4=X]"),
66 "all_good");
68 sub rr {
69 my ($state) = @_;
70 my $ostate = $state; # original
72 MogileFS::Factory::Host->t_wipe;
73 MogileFS::Factory::Device->t_wipe;
74 MogileFS::Config->set_config_no_broadcast("min_free_space", 100);
75 my $hfac = MogileFS::Factory::Host->get_factory;
76 my $dfac = MogileFS::Factory::Device->get_factory;
78 my $min = 2;
79 if ($state =~ s/^\bmin=(\d+)\b//) {
80 $min = $1;
83 my $hosts = {};
84 my $devs = {};
85 my $on_devs = [];
87 my $parse_error = sub {
88 die "Can't parse:\n $ostate\n"
90 while ($state =~ s/\bh(\d+)(?:=(.+?))?\[(.+?)\]//) {
91 my ($n, $opts, $devstr) = ($1, $2, $3);
92 $opts ||= "";
93 die "dup host $n" if $hosts->{$n};
95 my $h = $hosts->{$n} = $hfac->set({ hostid => $n,
96 status => ($opts || "alive"), observed_state => "reachable",
97 hostname => $n });
99 foreach my $ddecl (split(/\s+/, $devstr)) {
100 $ddecl =~ /^d(\d+)=([_X])(?:,(\w+))?$/
101 or $parse_error->();
102 my ($dn, $on_not, $status) = ($1, $2, $3);
103 die "dup device $dn" if $devs->{$dn};
104 my $d = $devs->{$dn} = $dfac->set({ devid => $dn,
105 hostid => $h->id, observed_state => "writeable",
106 status => ($status || "alive"), mb_total => 1000,
107 mb_used => 100, });
108 if ($on_not eq "X" && $d->dstate->should_have_files) {
109 push @$on_devs, $d;
113 $parse_error->() if $state =~ /\S/;
115 my $polclass = "MogileFS::ReplicationPolicy::MultipleHosts";
116 my $pol = $polclass->new;
117 my $rr = $pol->replicate_to(
118 fid => 1,
119 on_devs => $on_devs,
120 all_devs => $devs,
121 failed => {},
122 min => $min,
124 return $rr->t_as_string;