test: cover ClusterConfigService.WaitForQuorum

Returns once quorate, throws TimeoutException when quorum never arrives,
and keeps polling through a PveApiException from the restarting API.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
goodolclint-claude[bot]
2026-09-01 06:22:55 +00:00
committed by GitHub
parent 6881e5c53c
commit 2df9f47e2d
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Moq;
using Newtonsoft.Json.Linq;
using Xunit;
using PSProxmoxVE.Core.Authentication;
using PSProxmoxVE.Core.Client;
using PSProxmoxVE.Core.Exceptions;
using PSProxmoxVE.Core.Services;
namespace PSProxmoxVE.Core.Tests.Services
@@ -466,5 +468,49 @@ namespace PSProxmoxVE.Core.Tests.Services
{
Assert.Throws<ArgumentNullException>(() => new ClusterConfigService(null!));
}
[Fact]
public void WaitForQuorum_ReturnsOnceClusterIsQuorate()
{
var notQuorate = @"{""data"": [{""type"": ""cluster"", ""name"": ""c1"", ""quorate"": 0}]}";
var quorate = @"{""data"": [{""type"": ""cluster"", ""name"": ""c1"", ""quorate"": 1}]}";
var mockClient = new Mock<IPveHttpClient>();
mockClient.SetupSequence(c => c.GetAsync("cluster/status"))
.ReturnsAsync(notQuorate)
.ReturnsAsync(quorate);
var service = new ClusterConfigService(mockClient.Object);
service.WaitForQuorum(CreateSession(), TimeSpan.FromSeconds(30));
mockClient.Verify(c => c.GetAsync("cluster/status"), Times.Exactly(2));
}
[Fact]
public void WaitForQuorum_ThrowsWhenQuorumNeverReached()
{
var notQuorate = @"{""data"": [{""type"": ""cluster"", ""name"": ""c1"", ""quorate"": 0}]}";
var mockClient = new Mock<IPveHttpClient>();
mockClient.Setup(c => c.GetAsync("cluster/status")).ReturnsAsync(notQuorate);
var service = new ClusterConfigService(mockClient.Object);
Assert.Throws<TimeoutException>(() =>
service.WaitForQuorum(CreateSession(), TimeSpan.FromMilliseconds(1)));
}
[Fact]
public void WaitForQuorum_RetriesWhileTheApiIsRestarting()
{
var quorate = @"{""data"": [{""type"": ""cluster"", ""name"": ""c1"", ""quorate"": 1}]}";
var mockClient = new Mock<IPveHttpClient>();
mockClient.SetupSequence(c => c.GetAsync("cluster/status"))
.ThrowsAsync(new PveApiException(HttpStatusCode.InternalServerError,
"cluster not ready", "cluster/status", "GET"))
.ReturnsAsync(quorate);
var service = new ClusterConfigService(mockClient.Object);
service.WaitForQuorum(CreateSession(), TimeSpan.FromSeconds(30));
mockClient.Verify(c => c.GetAsync("cluster/status"), Times.Exactly(2));
}
}
}