mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-13 15:46:52 +00:00
test: add xUnit unit tests for core library
144 tests covering authentication (version parsing, session expiry, token format validation), model deserialization from real PVE 8.x/9.x API JSON fixtures, and service layer behavior. Includes TestHelper with mock HttpMessageHandler factory and 21 JSON fixture files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using PSProxmoxVE.Core.Authentication;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for PveAuthenticator input validation. These tests exercise the
|
||||
/// argument-validation logic without making actual HTTP calls.
|
||||
/// </summary>
|
||||
public class PveAuthenticatorTests
|
||||
{
|
||||
private const string ValidHostname = "pve.example.com";
|
||||
private const int ValidPort = 8006;
|
||||
|
||||
[Fact]
|
||||
public void ValidateUsername_MissingAtSign_Throws()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
PveAuthenticator.AuthenticateWithCredentials(ValidHostname, ValidPort, false, "rootpam", "password"));
|
||||
|
||||
Assert.Contains("realm", ex.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateApiToken_InvalidFormat_NoTokenId_Throws()
|
||||
{
|
||||
// Missing the !TOKENID part — no exclamation mark
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
PveAuthenticator.AuthenticateWithApiToken(ValidHostname, ValidPort, false, "root@pam=someuuid"));
|
||||
|
||||
Assert.Contains("token", ex.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateApiToken_InvalidFormat_NoEquals_Throws()
|
||||
{
|
||||
// Has ! but no = sign after TOKENID
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
PveAuthenticator.AuthenticateWithApiToken(ValidHostname, ValidPort, false, "root@pam!mytoken"));
|
||||
|
||||
Assert.Contains("token", ex.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateApiToken_InvalidFormat_NoRealm_Throws()
|
||||
{
|
||||
// Missing the @realm portion
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
PveAuthenticator.AuthenticateWithApiToken(ValidHostname, ValidPort, false, "root!mytoken=someuuid"));
|
||||
|
||||
Assert.Contains("token", ex.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void ValidateHostname_NullOrEmpty_Throws_ForCredentials(string hostname)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
PveAuthenticator.AuthenticateWithCredentials(hostname, ValidPort, false, "root@pam", "password"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void ValidateHostname_NullOrEmpty_Throws_ForApiToken(string hostname)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
PveAuthenticator.AuthenticateWithApiToken(hostname, ValidPort, false, "root@pam!mytoken=uuid"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void ValidateApiToken_NullOrEmpty_Throws(string token)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
PveAuthenticator.AuthenticateWithApiToken(ValidHostname, ValidPort, false, token));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using PSProxmoxVE.Core.Authentication;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Authentication
|
||||
{
|
||||
public class PveSessionTests
|
||||
{
|
||||
private const string TestHostname = "pve.example.com";
|
||||
private const int TestPort = 8006;
|
||||
|
||||
[Fact]
|
||||
public void TicketSession_NotExpired_OnCreation()
|
||||
{
|
||||
var expiry = DateTime.UtcNow.AddHours(2);
|
||||
var session = new PveSession(TestHostname, TestPort, false, "PVE:root@pam:TICKET", "CSRFTOKEN", expiry);
|
||||
|
||||
Assert.False(session.IsExpired);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TicketSession_IsExpired_After2Hours()
|
||||
{
|
||||
// Simulate a ticket that already expired an hour ago
|
||||
var expiry = DateTime.UtcNow.AddHours(-1);
|
||||
var session = new PveSession(TestHostname, TestPort, false, "PVE:root@pam:OLDTICKET", "CSRFTOKEN", expiry);
|
||||
|
||||
Assert.True(session.IsExpired);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApiTokenSession_NeverExpires()
|
||||
{
|
||||
var session = new PveSession(TestHostname, TestPort, false, "root@pam!mytoken=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
|
||||
|
||||
Assert.False(session.IsExpired);
|
||||
Assert.Equal(PveAuthMode.ApiToken, session.AuthMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BaseUrl_CorrectFormat()
|
||||
{
|
||||
var session = new PveSession(TestHostname, TestPort, false, "root@pam!mytoken=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
|
||||
|
||||
Assert.Equal($"https://{TestHostname}:{TestPort}/api2/json", session.BaseUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TicketSession_AuthMode_IsTicket()
|
||||
{
|
||||
var expiry = DateTime.UtcNow.AddHours(2);
|
||||
var session = new PveSession(TestHostname, TestPort, false, "PVE:root@pam:TICKET", "CSRFTOKEN", expiry);
|
||||
|
||||
Assert.Equal(PveAuthMode.Ticket, session.AuthMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SeparateSessions_DoNotShareState()
|
||||
{
|
||||
var expiry1 = DateTime.UtcNow.AddHours(2);
|
||||
var session1 = new PveSession("host1", 8006, false, "PVE:root@pam:TICKET1", "CSRF1", expiry1);
|
||||
var session2 = new PveSession("host2", 8006, false, "root@pam!token=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
|
||||
|
||||
Assert.NotEqual(session1.Hostname, session2.Hostname);
|
||||
Assert.Equal(PveAuthMode.Ticket, session1.AuthMode);
|
||||
Assert.Equal(PveAuthMode.ApiToken, session2.AuthMode);
|
||||
Assert.Equal("PVE:root@pam:TICKET1", session1.Ticket);
|
||||
Assert.Null(session1.ApiToken);
|
||||
Assert.Null(session2.Ticket);
|
||||
Assert.NotNull(session2.ApiToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TicketSession_StoresTicketAndCsrf()
|
||||
{
|
||||
var expiry = DateTime.UtcNow.AddHours(2);
|
||||
const string ticket = "PVE:root@pam:ABCD1234";
|
||||
const string csrf = "CSRFPREVENTION";
|
||||
|
||||
var session = new PveSession(TestHostname, TestPort, false, ticket, csrf, expiry);
|
||||
|
||||
Assert.Equal(ticket, session.Ticket);
|
||||
Assert.Equal(csrf, session.CsrfToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApiTokenSession_StoresApiToken()
|
||||
{
|
||||
const string token = "root@pam!mytoken=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
|
||||
var session = new PveSession(TestHostname, TestPort, false, token);
|
||||
|
||||
Assert.Equal(token, session.ApiToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SkipCertificateCheck_IsStored()
|
||||
{
|
||||
var session = new PveSession(TestHostname, TestPort, skipCertificateCheck: true,
|
||||
"root@pam!mytoken=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
|
||||
|
||||
Assert.True(session.SkipCertificateCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using PSProxmoxVE.Core.Authentication;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Authentication
|
||||
{
|
||||
public class PveVersionTests
|
||||
{
|
||||
[Fact]
|
||||
public void Parse_ValidVersion_9_1()
|
||||
{
|
||||
var version = PveVersion.Parse("9.1-1");
|
||||
Assert.Equal(9, version.Major);
|
||||
Assert.Equal(1, version.Minor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_ValidVersion_8_3()
|
||||
{
|
||||
var version = PveVersion.Parse("8.3-2");
|
||||
Assert.Equal(8, version.Major);
|
||||
Assert.Equal(3, version.Minor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_ValidVersion_8_0()
|
||||
{
|
||||
var version = PveVersion.Parse("8.0-1");
|
||||
Assert.Equal(8, version.Major);
|
||||
Assert.Equal(0, version.Minor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_NoPatchLevel()
|
||||
{
|
||||
var version = PveVersion.Parse("9.1");
|
||||
Assert.Equal(9, version.Major);
|
||||
Assert.Equal(1, version.Minor);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void Parse_NullOrEmpty_Throws(string input)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => PveVersion.Parse(input));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_InvalidFormat_Throws()
|
||||
{
|
||||
Assert.Throws<FormatException>(() => PveVersion.Parse("invalid"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsAtLeast_True_SameMajorLowerMinor()
|
||||
{
|
||||
var version = PveVersion.Parse("9.1-1");
|
||||
Assert.True(version.IsAtLeast(9, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsAtLeast_True_LowerMajor()
|
||||
{
|
||||
var version = PveVersion.Parse("9.1-1");
|
||||
Assert.True(version.IsAtLeast(8, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsAtLeast_False()
|
||||
{
|
||||
var version = PveVersion.Parse("8.3-2");
|
||||
Assert.False(version.IsAtLeast(9, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsAtLeast_ExactMatch()
|
||||
{
|
||||
var version = PveVersion.Parse("8.0-1");
|
||||
Assert.True(version.IsAtLeast(8, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToString_Format()
|
||||
{
|
||||
var version = PveVersion.Parse("9.1-1");
|
||||
Assert.Equal("9.1", version.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"node":"pve-old","status":"online","maxcpu":4,"maxmem":16106127360,"mem":4294967296,"uptime":172800,"pveversion":"pve-manager/8.3-2/12345678","kversion":"6.5.13-6-pve","loadavg":["0.10","0.15","0.12"]}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":{"version":"8.3-2","release":"8.3","repoid":"12345678","console":"xtermjs","keyboard":"en-us"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"type":"cluster","name":"testcluster","nodes":3,"quorate":1,"version":3},{"type":"node","name":"pve1","online":1,"local":1,"nodeid":1,"ip":"192.168.1.10","level":""},{"type":"node","name":"pve2","online":1,"local":0,"nodeid":2,"ip":"192.168.1.11","level":""},{"type":"node","name":"pve3","online":0,"local":0,"nodeid":3,"ip":"192.168.1.12","level":""}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"vmid":200,"name":"ct-web","status":"running","node":"pve1","cpus":2,"maxmem":2147483648,"maxswap":536870912,"maxdisk":8589934592,"ostype":"ubuntu","unprivileged":1,"uptime":43200,"tags":"web"},{"vmid":201,"name":"ct-db","status":"stopped","node":"pve1","cpus":1,"maxmem":1073741824,"maxswap":268435456,"maxdisk":4294967296,"ostype":"debian","unprivileged":1,"uptime":0}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"iface":"vmbr0","type":"bridge","address":"192.168.1.10","netmask":"255.255.255.0","gateway":"192.168.1.1","bridge_ports":"enp0s31f6","autostart":1,"active":1,"cidr":"192.168.1.10/24"},{"iface":"vmbr1","type":"bridge","address":"10.0.0.1","netmask":"255.255.255.0","bridge_ports":"enp2s0","autostart":1,"active":1,"cidr":"10.0.0.1/24","bridge_vlan_aware":1}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":{"node":"pve1","status":"online","maxcpu":16,"maxmem":68719476736,"mem":17179869184,"uptime":864000,"cpu":0.125,"rootfs":{"total":107374182400,"used":21474836480,"avail":85899345920,"free":85899345920},"swap":{"total":8589934592,"used":1073741824,"free":7516192768},"netin":549755813888,"netout":274877906944,"loadavg":["0.45","0.32","0.28"],"pveversion":"pve-manager/9.1-1/abcdef12","kversion":"6.8.12-5-pve"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"node":"pve1","status":"online","maxcpu":16,"maxmem":68719476736,"mem":17179869184,"uptime":864000,"pveversion":"pve-manager/9.1-1/abcdef12","kversion":"6.8.12-5-pve","loadavg":["0.45","0.32","0.28"]},{"node":"pve2","status":"online","maxcpu":8,"maxmem":34359738368,"mem":8589934592,"uptime":432000,"pveversion":"pve-manager/9.1-1/abcdef12","kversion":"6.8.12-5-pve","loadavg":["0.12","0.08","0.06"]}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"roleid":"Administrator","privs":"Datastore.Allocate,Datastore.AllocateSpace,Datastore.AllocateTemplate,Datastore.Audit,Group.Allocate,Mapping.Audit,Mapping.Modify,Mapping.Use,Permissions.Modify,Pool.Allocate,Pool.Audit,Realm.Allocate,Realm.AllocateUser,SDN.Allocate,SDN.Audit,SDN.Use,Sys.Audit,Sys.Console,Sys.Incoming,Sys.Modify,Sys.PowerMgmt,Sys.Syslog,User.Modify,VM.Allocate,VM.Audit,VM.Backup,VM.Clone,VM.Config.CDROM,VM.Config.CPU,VM.Config.Cloudinit,VM.Config.Disk,VM.Config.HWType,VM.Config.Memory,VM.Config.Net,VM.Config.Options,VM.Console,VM.Migrate,VM.Monitor,VM.PowerMgmt,VM.Snapshot,VM.Snapshot.Rollback","special":1},{"roleid":"PVEAuditor","privs":"Datastore.Audit,Mapping.Audit,Pool.Audit,SDN.Audit,Sys.Audit,VM.Audit","special":1}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"vnet":"myvnet","zone":"localzone","tag":100,"alias":"My VNET"},{"vnet":"prodnet","zone":"vxlanzone","tag":200,"alias":"Production Network","vlanaware":1}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"zone":"localzone","type":"simple","dns":"","reversedns":"","dnszone":"","mtu":1500,"pending":0},{"zone":"vxlanzone","type":"vxlan","dns":"","reversedns":"","dnszone":"","mtu":1450,"nodes":"pve1,pve2","pending":0}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"name":"current","description":"You are here!","snaptime":0,"parent":"snap1"},{"name":"snap1","description":"Before upgrade","snaptime":1710000000,"vmstate":1,"parent":"base"},{"name":"base","description":"Initial setup","snaptime":1709000000,"vmstate":0}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"storage":"local","type":"dir","content":"iso,vztmpl,backup","total":107374182400,"used":21474836480,"avail":85899345920,"enabled":1,"shared":0,"active":1},{"storage":"local-lvm","type":"lvmthin","content":"images,rootdir","total":536870912000,"used":107374182400,"avail":429496729600,"enabled":1,"shared":0,"active":1},{"storage":"ceph-pool","type":"rbd","content":"images","total":1099511627776,"used":214748364800,"avail":884763262976,"enabled":1,"shared":1,"active":1}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"volid":"local:iso/ubuntu-24.04-live-server-amd64.iso","content":"iso","format":"iso","size":2774532096,"ctime":1710000000},{"volid":"local:iso/debian-12.5.0-amd64-netinst.iso","content":"iso","format":"iso","size":658505728,"ctime":1709000000}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":{"upid":"UPID:pve1:00001234:00ABCDEF:65F00000:qmstart:100:root@pam:","type":"qmstart","status":"running","node":"pve1","starttime":1710000000,"user":"root@pam","id":"100"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":{"upid":"UPID:pve1:00001234:00ABCDEF:65F00000:qmstart:100:root@pam:","type":"qmstart","status":"stopped","exitstatus":"OK","node":"pve1","starttime":1710000000,"endtime":1710000010,"user":"root@pam","id":"100"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":{"username":"root@pam","ticket":"PVE:root@pam:65F00000::abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890","CSRFPreventionToken":"65F00000:abcdef1234567890abcdef12"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"userid":"root@pam","firstname":"Root","lastname":"User","email":"root@example.com","enable":1,"realm":"pam","expire":0},{"userid":"admin@pve","firstname":"Admin","lastname":"User","email":"admin@example.com","enable":1,"realm":"pve","groups":"admins","expire":0},{"userid":"readonly@pve","firstname":"Read","lastname":"Only","email":"readonly@example.com","enable":1,"realm":"pve","groups":"audit","comment":"Read-only audit user","expire":0}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":{"version":"9.1-1","release":"9.1","repoid":"abcdef12","console":"xtermjs","keyboard":"en-us"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":{"cores":4,"sockets":1,"memory":8192,"cpu":"host","bios":"ovmf","machine":"q35","boot":"order=scsi0;net0","description":"Test VM","tags":"prod;web","protection":0,"numa":0,"balloon":0,"ostype":"l26","virtio0":"local-lvm:vm-100-disk-0,size=100G","net0":"virtio=AA:BB:CC:DD:EE:FF,bridge=vmbr0,firewall=1","ide2":"local:iso/ubuntu-24.04-live-server-amd64.iso,media=cdrom","scsi0":"local-lvm:vm-100-disk-0,size=100G","scsihw":"virtio-scsi-single","ciuser":"admin","nameserver":"8.8.8.8","searchdomain":"example.com","ipconfig0":"ip=dhcp"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"data":[{"vmid":100,"name":"test-vm-1","status":"running","node":"pve1","cpus":4,"maxmem":8589934592,"maxdisk":107374182400,"uptime":86400,"tags":"prod;web","template":0,"pid":12345,"qmpstatus":"running","agent":1},{"vmid":101,"name":"test-vm-2","status":"stopped","node":"pve1","cpus":2,"maxmem":4294967296,"maxdisk":53687091200,"uptime":0,"tags":"dev","template":0},{"vmid":9000,"name":"ubuntu-template","status":"stopped","node":"pve1","cpus":2,"maxmem":4294967296,"maxdisk":53687091200,"uptime":0,"template":1}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"errors":{"vmid":"property is missing and it is not optional"},"data":null}
|
||||
@@ -0,0 +1,135 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Cluster;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class ClusterModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal(4, entries.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_FirstEntry_IsClusterType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal("cluster", entries[0].Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_ClusterEntry_HasCorrectName()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal("testcluster", entries[0].Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_ClusterEntry_HasNodeCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal(3, entries[0].Nodes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_ClusterEntry_IsQuorate()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal(1, entries[0].Quorate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_SecondEntry_IsNodeType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal("node", entries[1].Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_FirstNodeEntry_HasCorrectIp()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal("192.168.1.10", entries[1].Ip);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_FirstNodeEntry_IsOnline()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal(1, entries[1].Online);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_FirstNodeEntry_IsLocal()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
Assert.Equal(1, entries[1].Local);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_ThirdNode_IsOffline()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
// Fourth entry (index 3) is pve3 which is offline
|
||||
Assert.Equal("node", entries[3].Type);
|
||||
Assert.Equal(0, entries[3].Online);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_NodeFields_NullForClusterEntry()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
// Cluster-type entry should not have node-specific fields
|
||||
Assert.Null(entries[0].Ip);
|
||||
Assert.Null(entries[0].Online);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveClusterStatus_Deserialize_Pve9_ClusterFields_NullForNodeEntry()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_cluster_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var entries = data.ToObject<PveClusterStatus[]>();
|
||||
Assert.NotNull(entries);
|
||||
// Node-type entries should not have cluster-specific fields
|
||||
Assert.Null(entries[1].Nodes);
|
||||
Assert.Null(entries[1].Quorate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Containers;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class ContainerModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal(2, containers.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_HasCorrectVmId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal(200, containers[0].VmId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_HasCorrectName()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal("ct-web", containers[0].Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_HasCorrectStatus()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal("running", containers[0].Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_HasCorrectNode()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal("pve1", containers[0].Node);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_HasCorrectCpuAndMem()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal(2, containers[0].CpuCount);
|
||||
Assert.Equal(2147483648L, containers[0].MaxMem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_HasSwapAndDisk()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal(536870912L, containers[0].MaxSwap);
|
||||
Assert.Equal(8589934592L, containers[0].RootFsSize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_IsUnprivileged()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal(1, containers[0].Unprivileged);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_FirstContainer_HasOsType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal("ubuntu", containers[0].OsType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_Deserialize_Pve9_SecondContainer_IsStopped()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
Assert.Equal(201, containers[1].VmId);
|
||||
Assert.Equal("stopped", containers[1].Status);
|
||||
Assert.Equal(0L, containers[1].Uptime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveContainer_OptionalFields_NullWhenMissing()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_containers.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var containers = data.ToObject<PveContainer[]>();
|
||||
Assert.NotNull(containers);
|
||||
// Tags field is only in the first container
|
||||
Assert.Equal("web", containers[0].Tags);
|
||||
Assert.Null(containers[1].Tags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Network;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class NetworkModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal(2, networks.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_FirstInterface_HasCorrectName()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal("vmbr0", networks[0].Iface);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_FirstInterface_HasCorrectType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal("bridge", networks[0].Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_FirstInterface_HasCorrectAddress()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal("192.168.1.10", networks[0].Address);
|
||||
Assert.Equal("255.255.255.0", networks[0].Netmask);
|
||||
Assert.Equal("192.168.1.1", networks[0].Gateway);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_FirstInterface_HasCidr()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal("192.168.1.10/24", networks[0].Cidr);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_FirstInterface_HasBridgePorts()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal("enp0s31f6", networks[0].BridgePorts);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_FirstInterface_Autostart_IsEnabled()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal(1, networks[0].Autostart);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_OptionalFields_NullWhenMissing()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
// No VLAN on primary bridge
|
||||
Assert.Null(networks[0].VlanId);
|
||||
Assert.Null(networks[0].Comments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNetwork_Deserialize_Pve9_SecondInterface_HasCorrectAddress()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_networks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var networks = data.ToObject<PveNetwork[]>();
|
||||
Assert.NotNull(networks);
|
||||
Assert.Equal("vmbr1", networks[1].Iface);
|
||||
Assert.Equal("10.0.0.1/24", networks[1].Cidr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Nodes;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class NodeModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveNode_Deserialize_Pve9()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_nodes.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var nodes = data.ToObject<PveNode[]>();
|
||||
Assert.NotNull(nodes);
|
||||
Assert.Equal(2, nodes.Length);
|
||||
Assert.Equal("pve1", nodes[0].Name);
|
||||
Assert.Equal("online", nodes[0].Status);
|
||||
Assert.Equal(16, nodes[0].CpuCount);
|
||||
Assert.Equal(68719476736L, nodes[0].MemoryTotal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNode_Deserialize_Pve9_SecondNode()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_nodes.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var nodes = data.ToObject<PveNode[]>();
|
||||
Assert.NotNull(nodes);
|
||||
Assert.Equal("pve2", nodes[1].Name);
|
||||
Assert.Equal("online", nodes[1].Status);
|
||||
Assert.Equal(8, nodes[1].CpuCount);
|
||||
Assert.Equal(34359738368L, nodes[1].MemoryTotal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNode_Deserialize_Pve8()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve8_nodes.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var nodes = data.ToObject<PveNode[]>();
|
||||
Assert.NotNull(nodes);
|
||||
Assert.Single(nodes);
|
||||
Assert.Equal("pve-old", nodes[0].Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNode_Deserialize_Pve8_HasExpectedCpuAndMemory()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve8_nodes.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var nodes = data.ToObject<PveNode[]>();
|
||||
Assert.NotNull(nodes);
|
||||
Assert.Equal(4, nodes[0].CpuCount);
|
||||
Assert.Equal(16106127360L, nodes[0].MemoryTotal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNodeStatus_Deserialize_Pve9()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_node_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var status = data.ToObject<PveNodeStatus>();
|
||||
Assert.NotNull(status);
|
||||
Assert.Equal(0.125, status.CpuUsage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNodeStatus_Deserialize_Pve9_HasMemoryAndUptime()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_node_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var status = data.ToObject<PveNodeStatus>();
|
||||
Assert.NotNull(status);
|
||||
Assert.Equal("pve1", status.Name);
|
||||
Assert.Equal(68719476736L, status.MemoryTotal);
|
||||
Assert.Equal(17179869184L, status.MemoryUsed);
|
||||
Assert.Equal(864000L, status.Uptime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNodeStatus_MemoryUsage_IsCalculated()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_node_status.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var status = data.ToObject<PveNodeStatus>();
|
||||
Assert.NotNull(status);
|
||||
Assert.NotNull(status.MemoryUsage);
|
||||
// 17179869184 / 68719476736 * 100 = 25.0
|
||||
Assert.Equal(25.0, status.MemoryUsage!.Value, precision: 5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveNode_LoadAverage_IsDeserializedAsArray()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_nodes.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var nodes = data.ToObject<PveNode[]>();
|
||||
Assert.NotNull(nodes);
|
||||
Assert.NotNull(nodes[0].LoadAverage);
|
||||
Assert.Equal(3, nodes[0].LoadAverage!.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Network;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class SdnModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveSdnZone_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_zones.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var zones = data.ToObject<PveSdnZone[]>();
|
||||
Assert.NotNull(zones);
|
||||
Assert.Equal(2, zones.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnZone_Deserialize_Pve9_FirstZone_HasCorrectId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_zones.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var zones = data.ToObject<PveSdnZone[]>();
|
||||
Assert.NotNull(zones);
|
||||
Assert.Equal("localzone", zones[0].Zone);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnZone_Deserialize_Pve9_FirstZone_HasCorrectType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_zones.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var zones = data.ToObject<PveSdnZone[]>();
|
||||
Assert.NotNull(zones);
|
||||
Assert.Equal("simple", zones[0].Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnZone_Deserialize_Pve9_SecondZone_HasCorrectType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_zones.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var zones = data.ToObject<PveSdnZone[]>();
|
||||
Assert.NotNull(zones);
|
||||
Assert.Equal("vxlanzone", zones[1].Zone);
|
||||
Assert.Equal("vxlan", zones[1].Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnZone_Deserialize_Pve9_OptionalFields_NullWhenMissing()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_zones.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var zones = data.ToObject<PveSdnZone[]>();
|
||||
Assert.NotNull(zones);
|
||||
// Comments field is not present in the fixture
|
||||
Assert.Null(zones[0].Comments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnVnet_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_vnets.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vnets = data.ToObject<PveSdnVnet[]>();
|
||||
Assert.NotNull(vnets);
|
||||
Assert.Equal(2, vnets.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnVnet_Deserialize_Pve9_FirstVnet_HasCorrectId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_vnets.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vnets = data.ToObject<PveSdnVnet[]>();
|
||||
Assert.NotNull(vnets);
|
||||
Assert.Equal("myvnet", vnets[0].Vnet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnVnet_Deserialize_Pve9_FirstVnet_HasCorrectZone()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_vnets.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vnets = data.ToObject<PveSdnVnet[]>();
|
||||
Assert.NotNull(vnets);
|
||||
Assert.Equal("localzone", vnets[0].Zone);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnVnet_Deserialize_Pve9_FirstVnet_HasTag()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_vnets.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vnets = data.ToObject<PveSdnVnet[]>();
|
||||
Assert.NotNull(vnets);
|
||||
Assert.Equal(100, vnets[0].Tag);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnVnet_Deserialize_Pve9_FirstVnet_HasAlias()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_vnets.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vnets = data.ToObject<PveSdnVnet[]>();
|
||||
Assert.NotNull(vnets);
|
||||
Assert.Equal("My VNET", vnets[0].Alias);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnVnet_Deserialize_Pve9_SecondVnet_HasCorrectZoneAndTag()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_vnets.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vnets = data.ToObject<PveSdnVnet[]>();
|
||||
Assert.NotNull(vnets);
|
||||
Assert.Equal("prodnet", vnets[1].Vnet);
|
||||
Assert.Equal("vxlanzone", vnets[1].Zone);
|
||||
Assert.Equal(200, vnets[1].Tag);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSdnVnet_Deserialize_Pve9_OptionalFields_NullWhenMissing()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_sdn_vnets.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vnets = data.ToObject<PveSdnVnet[]>();
|
||||
Assert.NotNull(vnets);
|
||||
// Comments not present in fixture entries
|
||||
Assert.Null(vnets[0].Comments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Vms;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class SnapshotModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal(3, snapshots.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Current_HasCorrectName()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal("current", snapshots[0].Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Current_HasDescription()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal("You are here!", snapshots[0].Description);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Snap1_HasSnapTime()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal("snap1", snapshots[1].Name);
|
||||
Assert.Equal(1710000000L, snapshots[1].SnapTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Snap1_HasVmState()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal(1, snapshots[1].VmState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Snap1_HasParent()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal("base", snapshots[1].Parent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Base_HasNoVmState()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal("base", snapshots[2].Name);
|
||||
Assert.Equal(0, snapshots[2].VmState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Current_ParentIsSnap1()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal("snap1", snapshots[0].Parent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveSnapshot_Deserialize_Pve9_Base_HasOlderSnapTime()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_snapshots.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var snapshots = data.ToObject<PveSnapshot[]>();
|
||||
Assert.NotNull(snapshots);
|
||||
Assert.Equal(1709000000L, snapshots[2].SnapTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Storage;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class StorageModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveStorage_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var storages = data.ToObject<PveStorage[]>();
|
||||
Assert.NotNull(storages);
|
||||
Assert.Equal(3, storages.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorage_Deserialize_Pve9_Local_HasCorrectId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var storages = data.ToObject<PveStorage[]>();
|
||||
Assert.NotNull(storages);
|
||||
Assert.Equal("local", storages[0].Storage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorage_Deserialize_Pve9_Local_HasCorrectType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var storages = data.ToObject<PveStorage[]>();
|
||||
Assert.NotNull(storages);
|
||||
Assert.Equal("dir", storages[0].Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorage_Deserialize_Pve9_Local_HasContentTypes()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var storages = data.ToObject<PveStorage[]>();
|
||||
Assert.NotNull(storages);
|
||||
Assert.Equal("iso,vztmpl,backup", storages[0].Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorage_Deserialize_Pve9_Local_HasSizeFields()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var storages = data.ToObject<PveStorage[]>();
|
||||
Assert.NotNull(storages);
|
||||
Assert.Equal(107374182400L, storages[0].Total);
|
||||
Assert.Equal(21474836480L, storages[0].Used);
|
||||
Assert.Equal(85899345920L, storages[0].Available);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorage_Deserialize_Pve9_Local_IsEnabled_NotShared()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var storages = data.ToObject<PveStorage[]>();
|
||||
Assert.NotNull(storages);
|
||||
Assert.Equal(1, storages[0].Enabled);
|
||||
Assert.Equal(0, storages[0].Shared);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorage_Deserialize_Pve9_CephPool_IsShared()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var storages = data.ToObject<PveStorage[]>();
|
||||
Assert.NotNull(storages);
|
||||
var ceph = storages[2];
|
||||
Assert.Equal("ceph-pool", ceph.Storage);
|
||||
Assert.Equal("rbd", ceph.Type);
|
||||
Assert.Equal(1, ceph.Shared);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorageContent_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage_content.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var items = data.ToObject<PveStorageContent[]>();
|
||||
Assert.NotNull(items);
|
||||
Assert.Equal(2, items.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorageContent_Deserialize_Pve9_FirstItem_HasCorrectVolId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage_content.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var items = data.ToObject<PveStorageContent[]>();
|
||||
Assert.NotNull(items);
|
||||
Assert.Equal("local:iso/ubuntu-24.04-live-server-amd64.iso", items[0].VolId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorageContent_Deserialize_Pve9_FirstItem_HasCorrectContentType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage_content.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var items = data.ToObject<PveStorageContent[]>();
|
||||
Assert.NotNull(items);
|
||||
Assert.Equal("iso", items[0].Content);
|
||||
Assert.Equal("iso", items[0].Format);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorageContent_Deserialize_Pve9_FirstItem_HasSize()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage_content.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var items = data.ToObject<PveStorageContent[]>();
|
||||
Assert.NotNull(items);
|
||||
Assert.Equal(2774532096L, items[0].Size);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveStorageContent_Deserialize_Pve9_OptionalFields_NullWhenMissing()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_storage_content.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var items = data.ToObject<PveStorageContent[]>();
|
||||
Assert.NotNull(items);
|
||||
// ISO items should not have a VmId or Notes
|
||||
Assert.Null(items[0].VmId);
|
||||
Assert.Null(items[0].Notes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Vms;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class TaskModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Completed_HasCorrectUpid()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_tasks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.Equal("UPID:pve1:00001234:00ABCDEF:65F00000:qmstart:100:root@pam:", task.Upid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Completed_StatusIsStopped()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_tasks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.Equal("stopped", task.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Completed_ExitStatusIsOk()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_tasks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.Equal("OK", task.ExitStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Completed_IsSuccessful_IsTrue()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_tasks.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.True(task.IsSuccessful);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Running_HasCorrectUpid()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_task_running.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.Equal("UPID:pve1:00001234:00ABCDEF:65F00000:qmstart:100:root@pam:", task.Upid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Running_StatusIsRunning()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_task_running.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.Equal("running", task.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Running_ExitStatus_IsNull()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_task_running.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.Null(task.ExitStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_Deserialize_Running_IsSuccessful_IsFalse()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_task_running.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var task = data.ToObject<PveTask>();
|
||||
Assert.NotNull(task);
|
||||
Assert.False(task.IsSuccessful);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveTask_IsSuccessful_RequiresBothStoppedAndOk()
|
||||
{
|
||||
// Stopped but with an error exit status should not be successful
|
||||
var task = new PveTask
|
||||
{
|
||||
Upid = "UPID:pve1:000:000:000:qmstop:100:root@pam:",
|
||||
Status = "stopped",
|
||||
ExitStatus = "Error: some error occurred"
|
||||
};
|
||||
Assert.False(task.IsSuccessful);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Users;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class UserModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
Assert.Equal(3, users.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_Root_HasCorrectUserId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
Assert.Equal("root@pam", users[0].UserId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_Root_HasCorrectName()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
Assert.Equal("Root", users[0].FirstName);
|
||||
Assert.Equal("User", users[0].LastName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_Root_HasEmail()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
Assert.Equal("root@example.com", users[0].Email);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_Root_IsEnabled()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
Assert.Equal(1, users[0].Enabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_Admin_HasGroups()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
Assert.Equal("admin@pve", users[1].UserId);
|
||||
Assert.Equal("admins", users[1].Groups);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_ReadOnly_HasComment()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
Assert.Equal("readonly@pve", users[2].UserId);
|
||||
Assert.Equal("Read-only audit user", users[2].Comment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveUser_Deserialize_Pve9_Root_Groups_IsNull()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_users.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var users = data.ToObject<PveUser[]>();
|
||||
Assert.NotNull(users);
|
||||
// Root user has no groups in fixture
|
||||
Assert.Null(users[0].Groups);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveRole_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_roles.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var roles = data.ToObject<PveRole[]>();
|
||||
Assert.NotNull(roles);
|
||||
Assert.Equal(2, roles.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveRole_Deserialize_Pve9_Administrator_HasCorrectId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_roles.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var roles = data.ToObject<PveRole[]>();
|
||||
Assert.NotNull(roles);
|
||||
Assert.Equal("Administrator", roles[0].RoleId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveRole_Deserialize_Pve9_Administrator_IsSpecial()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_roles.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var roles = data.ToObject<PveRole[]>();
|
||||
Assert.NotNull(roles);
|
||||
Assert.Equal(1, roles[0].Special);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveRole_Deserialize_Pve9_Administrator_HasPrivileges()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_roles.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var roles = data.ToObject<PveRole[]>();
|
||||
Assert.NotNull(roles);
|
||||
Assert.NotNull(roles[0].Privileges);
|
||||
Assert.Contains("VM.Allocate", roles[0].Privileges);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveRole_Deserialize_Pve9_PVEAuditor_HasLimitedPrivileges()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_roles.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var roles = data.ToObject<PveRole[]>();
|
||||
Assert.NotNull(roles);
|
||||
Assert.Equal("PVEAuditor", roles[1].RoleId);
|
||||
Assert.Contains("VM.Audit", roles[1].Privileges);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
using Xunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmoxVE.Core.Models.Vms;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests.Models
|
||||
{
|
||||
public class VmModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_ReturnsCorrectCount()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
Assert.Equal(3, vms.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_FirstVm_HasCorrectVmId()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
Assert.Equal(100, vms[0].VmId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_FirstVm_HasCorrectName()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
Assert.Equal("test-vm-1", vms[0].Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_FirstVm_HasCorrectStatus()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
Assert.Equal("running", vms[0].Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_TemplateFlag_IsSet()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
// Third entry is the template
|
||||
var template = vms[2];
|
||||
Assert.Equal(9000, template.VmId);
|
||||
Assert.Equal(1, template.Template);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_RegularVm_TemplateFlag_IsZero()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
Assert.Equal(0, vms[0].Template);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_FirstVm_HasExpectedMemoryAndDisk()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
Assert.Equal(8589934592L, vms[0].MaxMem);
|
||||
Assert.Equal(107374182400L, vms[0].MaxDisk);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVm_Deserialize_Pve9_StoppedVm_UptimeIsZero()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vms.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var vms = data.ToObject<PveVm[]>();
|
||||
Assert.NotNull(vms);
|
||||
Assert.Equal(0L, vms[1].Uptime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVmConfig_Deserialize_Pve9_HasCorrectCoresAndMemory()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vm_config.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var config = data.ToObject<PveVmConfig>();
|
||||
Assert.NotNull(config);
|
||||
Assert.Equal(4, config.Cores);
|
||||
Assert.Equal(1, config.Sockets);
|
||||
Assert.Equal(8192, config.Memory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVmConfig_Deserialize_Pve9_HasCorrectBiosAndMachine()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vm_config.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var config = data.ToObject<PveVmConfig>();
|
||||
Assert.NotNull(config);
|
||||
Assert.Equal("ovmf", config.Bios);
|
||||
Assert.Equal("q35", config.Machine);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVmConfig_Deserialize_Pve9_HasCpuTypeAndOsType()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vm_config.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var config = data.ToObject<PveVmConfig>();
|
||||
Assert.NotNull(config);
|
||||
Assert.Equal("host", config.CpuType);
|
||||
Assert.Equal("l26", config.OsType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVmConfig_Deserialize_Pve9_HasNetworkInterface()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vm_config.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var config = data.ToObject<PveVmConfig>();
|
||||
Assert.NotNull(config);
|
||||
Assert.NotNull(config.Net0);
|
||||
Assert.Contains("vmbr0", config.Net0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVmConfig_Deserialize_Pve9_OptionalFields_NullWhenMissing()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vm_config.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var config = data.ToObject<PveVmConfig>();
|
||||
Assert.NotNull(config);
|
||||
// Fields not present in fixture should be null
|
||||
Assert.Null(config.Net1);
|
||||
Assert.Null(config.Virtio1);
|
||||
Assert.Null(config.Args);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PveVmConfig_Deserialize_Pve9_CloudInitFields()
|
||||
{
|
||||
var json = TestHelper.LoadFixture("pve9_vm_config.json");
|
||||
var data = JObject.Parse(json)["data"];
|
||||
var config = data.ToObject<PveVmConfig>();
|
||||
Assert.NotNull(config);
|
||||
Assert.Equal("admin", config.CiUser);
|
||||
Assert.Equal("8.8.8.8", config.Nameserver);
|
||||
Assert.Equal("example.com", config.Searchdomain);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
|
||||
namespace PSProxmoxVE.Core.Tests
|
||||
{
|
||||
public static class TestHelper
|
||||
{
|
||||
public static string LoadFixture(string filename)
|
||||
{
|
||||
var path = Path.Combine("Fixtures", filename);
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
public static Mock<HttpMessageHandler> CreateMockHandler(string responseBody, HttpStatusCode statusCode = HttpStatusCode.OK)
|
||||
{
|
||||
var mock = new Mock<HttpMessageHandler>();
|
||||
mock.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = statusCode,
|
||||
Content = new StringContent(responseBody)
|
||||
});
|
||||
return mock;
|
||||
}
|
||||
|
||||
public static Mock<HttpMessageHandler> CreateMockHandlerSequence(params (string body, HttpStatusCode status)[] responses)
|
||||
{
|
||||
var mock = new Mock<HttpMessageHandler>();
|
||||
var setup = mock.Protected()
|
||||
.SetupSequence<Task<HttpResponseMessage>>("SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>());
|
||||
foreach (var (body, status) in responses)
|
||||
{
|
||||
setup = setup.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = status,
|
||||
Content = new StringContent(body)
|
||||
});
|
||||
}
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user