EV-Etcd
view release on metacpan or search on metacpan
t/election.t view on Meta::CPAN
if ($resp->{kv}) {
diag("Current leader value: $resp->{kv}{value}");
is($resp->{kv}{value}, "initial-value", 'leader value matches');
} else {
fail('leader value matches');
}
EV::break;
});
my $t3 = EV::timer(5, 0, sub { fail('timeout'); EV::break });
EV::run;
# Test 10-11: Proclaim new value
$client->election_proclaim($leader_key, "updated-value", sub {
my ($resp, $err) = @_;
ok(!$err, 'election_proclaim succeeded');
ok($resp->{header}, 'proclaim response has header');
EV::break;
});
my $t4 = EV::timer(5, 0, sub { fail('timeout'); EV::break });
EV::run;
# Test 12-13: Verify updated value
$client->election_leader($election_name, sub {
my ($resp, $err) = @_;
ok(!$err, 'election_leader after proclaim succeeded');
if ($resp->{kv}) {
is($resp->{kv}{value}, "updated-value", 'proclaimed value matches');
} else {
fail('proclaimed value matches');
}
EV::break;
});
my $t5 = EV::timer(5, 0, sub { fail('timeout'); EV::break });
EV::run;
# Test 14-15: Resign leadership
$client->election_resign($leader_key, sub {
my ($resp, $err) = @_;
ok(!$err, 'election_resign succeeded');
ok($resp->{header}, 'resign response has header');
EV::break;
});
my $t6 = EV::timer(5, 0, sub { fail('timeout'); EV::break });
EV::run;
# Test 16: Verify no leader after resign
$client->election_leader($election_name, sub {
my ($resp, $err) = @_;
ok($err, 'election_leader after resign returns error (no leader)');
if ($err) {
diag("Expected error after resign: $err->{status} - $err->{message}");
}
EV::break;
});
my $t7 = EV::timer(5, 0, sub { fail('timeout'); EV::break });
EV::run;
}
}
# Test 17-22: election_observe streaming test
{
my $observe_election = "observe-test-$$-" . time();
my $observe_lease_id;
my @observed_events;
my $observe_leader_key;
# Grant a lease for this test
$client->lease_grant(30, sub {
my ($resp, $err) = @_;
$observe_lease_id = $resp->{id} if !$err;
EV::break;
});
my $tl = EV::timer(5, 0, sub { EV::break });
EV::run;
SKIP: {
skip "no observe lease id", 6 unless $observe_lease_id;
# Test 17-18: Start observing the election
my $observe_handle = $client->election_observe($observe_election, sub {
my ($resp, $err) = @_;
if ($err) {
# Stream ended or error - this is expected after resign
push @observed_events, { error => $err };
} else {
push @observed_events, $resp;
diag("Observed leader change: " . ($resp->{kv} ? $resp->{kv}{value} : 'no kv'));
}
});
ok(defined $observe_handle, 'election_observe returns handle');
isa_ok($observe_handle, 'EV::Etcd::Observe', 'observe handle');
# Give observe stream time to set up
my $setup_wait = EV::timer(0.2, 0, sub { EV::break });
EV::run;
# Test 18-19: Campaign for leadership (should trigger observe callback)
$client->election_campaign($observe_election, $observe_lease_id, "observed-value", sub {
my ($resp, $err) = @_;
ok(!$err, 'election_campaign for observe test succeeded');
if ($resp->{leader}) {
$observe_leader_key = $resp->{leader};
ok($observe_leader_key->{name}, 'observe leader key has name');
} else {
fail('observe leader key has name');
}
EV::break;
});
my $t8 = EV::timer(5, 0, sub { fail('timeout in observe campaign'); EV::break });
EV::run;
# Wait for observe callback to fire - use a check watcher to poll
my $wait_count = 0;
my $check_timer;
$check_timer = EV::timer(0.1, 0.1, sub {
$wait_count++;
if (@observed_events || $wait_count > 20) {
undef $check_timer;
EV::break;
}
( run in 0.996 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )