mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-09-07 20:45:40 +00:00
a26b8d681d
* test: drop the null-session guard tests only a test can reach (#154, part C) Deletes xUnit tests across tests/PSProxmoxVE.Core.Tests/Services/ that assert ArgumentNullException for a null PveSession, or for a null string identifier fed only from a cmdlet parameter PowerShell's mandatory binding already blocks from being null. Both are paths only a test's null! literal can trigger; the guard code in src/ stays as documentation. Kept: constructor null-dependency guards, a null action to PveServiceBase.Invoke, null-argument tests on optional parameters or on service methods with no cmdlet caller, and whitespace-guard tests a real caller can still produce (mandatory binding blocks null/empty but not whitespace-only strings). * test: drop the null-session guard tests only a test can reach (#154, part C) [2/2] * test: drop the null-session guard tests only a test can reach (#154, part C) [3/3] * test: drop the null-session guard tests only a test can reach (#154, part C) [4/4] --------- Co-authored-by: goodolclint-claude[bot] <323206664+goodolclint-claude[bot]@users.noreply.github.com>
168 lines
6.2 KiB
C#
168 lines
6.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using Moq;
|
|
using Xunit;
|
|
using PSProxmoxVE.Core.Authentication;
|
|
using PSProxmoxVE.Core.Client;
|
|
using PSProxmoxVE.Core.Services;
|
|
|
|
namespace PSProxmoxVE.Core.Tests.Services
|
|
{
|
|
public class CloudInitServiceTests
|
|
{
|
|
private static PveSession CreateSession()
|
|
{
|
|
return new PveSession("pve.example.com", 8006, false,
|
|
"root@pam!testtoken=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
|
|
}
|
|
|
|
[Fact]
|
|
public void GetCloudInitConfig_ReturnsConfig()
|
|
{
|
|
// Arrange
|
|
var json = @"{""data"": {
|
|
""ciuser"": ""ubuntu"",
|
|
""ipconfig0"": ""ip=dhcp"",
|
|
""nameserver"": ""8.8.8.8"",
|
|
""searchdomain"": ""example.com"",
|
|
""sshkeys"": ""ssh-rsa%20AAAA...%20user%40host"",
|
|
""boot"": ""order=scsi0;net0"",
|
|
""cores"": 4,
|
|
""memory"": 8192
|
|
}}";
|
|
var mockClient = new Mock<IPveHttpClient>();
|
|
mockClient.Setup(c => c.GetAsync("nodes/pve1/qemu/100/config")).ReturnsAsync(json);
|
|
var service = new CloudInitService(mockClient.Object);
|
|
|
|
// Act
|
|
var config = service.GetCloudInitConfig(CreateSession(), "pve1", 100);
|
|
|
|
// Assert
|
|
Assert.NotNull(config);
|
|
Assert.Equal("ubuntu", config.CiUser);
|
|
Assert.Equal("ip=dhcp", config.IpConfig0);
|
|
Assert.Equal("8.8.8.8", config.Nameserver);
|
|
Assert.Equal("example.com", config.Searchdomain);
|
|
Assert.Equal("ssh-rsa%20AAAA...%20user%40host", config.SshKeys);
|
|
mockClient.Verify(c => c.GetAsync("nodes/pve1/qemu/100/config"), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetCloudInitConfig_ExcludesNonCiFields()
|
|
{
|
|
// Arrange — response includes non-CI fields that should be ignored
|
|
var json = @"{""data"": {
|
|
""ciuser"": ""admin"",
|
|
""cores"": 4,
|
|
""memory"": 8192,
|
|
""boot"": ""order=scsi0""
|
|
}}";
|
|
var mockClient = new Mock<IPveHttpClient>();
|
|
mockClient.Setup(c => c.GetAsync("nodes/pve1/qemu/200/config")).ReturnsAsync(json);
|
|
var service = new CloudInitService(mockClient.Object);
|
|
|
|
// Act
|
|
var config = service.GetCloudInitConfig(CreateSession(), "pve1", 200);
|
|
|
|
// Assert
|
|
Assert.Equal("admin", config.CiUser);
|
|
// Non-CI fields should not appear in the result
|
|
Assert.Null(config.IpConfig0);
|
|
Assert.Null(config.Nameserver);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetCloudInitConfig_CallsPutAsyncWithCorrectResource()
|
|
{
|
|
// Arrange
|
|
var mockClient = new Mock<IPveHttpClient>();
|
|
mockClient.Setup(c => c.PutAsync(
|
|
"nodes/pve1/qemu/100/config",
|
|
It.IsAny<Dictionary<string, string>>()))
|
|
.ReturnsAsync("{}");
|
|
var service = new CloudInitService(mockClient.Object);
|
|
var config = new Dictionary<string, object>
|
|
{
|
|
["ciuser"] = "ubuntu",
|
|
["ipconfig0"] = "ip=dhcp"
|
|
};
|
|
|
|
// Act
|
|
service.SetCloudInitConfig(CreateSession(), "pve1", 100, config);
|
|
|
|
// Assert
|
|
mockClient.Verify(c => c.PutAsync(
|
|
"nodes/pve1/qemu/100/config",
|
|
It.Is<Dictionary<string, string>>(d =>
|
|
d["ciuser"] == "ubuntu" && d["ipconfig0"] == "ip=dhcp")),
|
|
Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public void RegenerateCloudInitImage_CallsPutAsyncAndReturnsUpid()
|
|
{
|
|
// Arrange
|
|
var json = @"{""data"": ""UPID:pve1:00001234:00005678:12345678:cloudinit:100:root@pam:""}";
|
|
var mockClient = new Mock<IPveHttpClient>();
|
|
mockClient.Setup(c => c.PutAsync("nodes/pve1/qemu/100/cloudinit", null))
|
|
.ReturnsAsync(json);
|
|
var service = new CloudInitService(mockClient.Object);
|
|
|
|
// Act
|
|
var result = service.RegenerateCloudInitImage(CreateSession(), "pve1", 100);
|
|
|
|
// Assert
|
|
Assert.Contains("UPID:", result);
|
|
mockClient.Verify(c => c.PutAsync("nodes/pve1/qemu/100/cloudinit", null), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_NullClient_ThrowsArgumentNullException()
|
|
{
|
|
Assert.Throws<ArgumentNullException>(() => new CloudInitService(null!));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFullVmConfig_ReturnsFullConfig_IncludingCloudInitAndOtherFields()
|
|
{
|
|
// Arrange
|
|
var json = @"{""data"": {
|
|
""ciuser"": ""ubuntu"",
|
|
""ipconfig0"": ""ip=dhcp"",
|
|
""cores"": 4,
|
|
""memory"": 8192
|
|
}}";
|
|
var mockClient = new Mock<IPveHttpClient>();
|
|
mockClient.Setup(c => c.GetAsync("nodes/pve1/qemu/100/config")).ReturnsAsync(json);
|
|
var service = new CloudInitService(mockClient.Object);
|
|
|
|
// Act
|
|
var config = service.GetFullVmConfig(CreateSession(), "pve1", 100);
|
|
|
|
// Assert — cloud-init fields and every other config field are both present
|
|
Assert.Equal("ubuntu", config.CiUser);
|
|
Assert.Equal("ip=dhcp", config.IpConfig0);
|
|
Assert.Equal(4, config.Cores);
|
|
Assert.Equal(8192, config.Memory);
|
|
mockClient.Verify(c => c.GetAsync("nodes/pve1/qemu/100/config"), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFullVmConfig_EscapesNodeInPath()
|
|
{
|
|
// Arrange
|
|
var json = @"{""data"": {}}";
|
|
var mockClient = new Mock<IPveHttpClient>();
|
|
mockClient.Setup(c => c.GetAsync("nodes/pve%20node/qemu/100/config")).ReturnsAsync(json);
|
|
var service = new CloudInitService(mockClient.Object);
|
|
|
|
// Act
|
|
service.GetFullVmConfig(CreateSession(), "pve node", 100);
|
|
|
|
// Assert
|
|
mockClient.Verify(c => c.GetAsync("nodes/pve%20node/qemu/100/config"), Times.Once);
|
|
}
|
|
}
|
|
}
|