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 )