SystemDiscoveryTests.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using RackPeek.Domain.Discovery;
  2. using RackPeek.Domain.Resources.SystemResources;
  3. namespace Tests.Discovery;
  4. /// <summary>
  5. /// Host snapshot in, RackPeek YAML out. Nothing here touches the machine the tests
  6. /// run on, so a Linux host is inspected identically from macOS or Windows.
  7. /// </summary>
  8. public class SystemDiscoveryTests {
  9. private static RawSystemSnapshot LinuxSnapshot(
  10. string? machineId = "7f3c9a1e5b2d4f6081a3c5e7b9d1f3a5",
  11. string? cgroup = null,
  12. string? dmiVendor = "Dell Inc.",
  13. string? dmiProduct = "PowerEdge R730",
  14. string hostname = "nas01.lan") {
  15. return new RawSystemSnapshot {
  16. Hostname = hostname,
  17. Cores = 12,
  18. FallbackMemoryBytes = 1024L * 1024 * 1024,
  19. OsReleaseFile = Fixture.Read("linux-os-release"),
  20. MemInfoFile = Fixture.Read("linux-meminfo"),
  21. MachineIdFile = machineId,
  22. CgroupFile = cgroup ?? Fixture.Read("linux-cgroup-host"),
  23. DmiVendor = dmiVendor,
  24. DmiProduct = dmiProduct,
  25. Nics = [
  26. new NicFact("lo", true, true, false, "127.0.0.1"),
  27. new NicFact("docker0", true, false, false, "172.17.0.1"),
  28. new NicFact("eno1", true, false, true, "192.168.1.20")
  29. ],
  30. BlockDevices = [
  31. new BlockDeviceFact("nvme0n1", 1_000_204_886_016, false),
  32. new BlockDeviceFact("sda", 8_001_563_222_016, true),
  33. new BlockDeviceFact("loop0", 67_108_864, false),
  34. new BlockDeviceFact("sr0", 0, true)
  35. ]
  36. };
  37. }
  38. [Fact]
  39. public void Linux_host_maps_onto_a_complete_system_resource() {
  40. SystemFacts facts = SystemFactsParser.Parse(LinuxSnapshot());
  41. SystemResource resource = SystemResourceMapper.ToResource(facts);
  42. Assert.Equal("nas01", resource.Name);
  43. Assert.Equal("Debian GNU/Linux 12 (bookworm)", resource.Os);
  44. Assert.Equal("baremetal", resource.Type);
  45. Assert.Equal(12, resource.Cores);
  46. Assert.Equal("192.168.1.20", resource.Ip);
  47. Assert.StartsWith("rpk1:sys:", resource.DiscoveryId);
  48. }
  49. [Fact]
  50. public void Ram_comes_from_meminfo_which_reports_a_little_under_the_physical_total() {
  51. // 65790000 kB is what a 64 GB machine reports once the kernel has taken its share.
  52. // Reported as measured rather than rounded up to the DIMM size it was sold as.
  53. SystemFacts facts = SystemFactsParser.Parse(LinuxSnapshot());
  54. Assert.Equal(63, facts.RamGb);
  55. }
  56. [Fact]
  57. public void Physical_disks_are_kept_and_kernel_devices_are_not() {
  58. SystemFacts facts = SystemFactsParser.Parse(LinuxSnapshot());
  59. Assert.Collection(facts.Drives,
  60. nvme => {
  61. Assert.Equal("nvme", nvme.Type);
  62. Assert.Equal(932, nvme.SizeGb);
  63. },
  64. hdd => {
  65. Assert.Equal("hdd", hdd.Type);
  66. Assert.Equal(7452, hdd.SizeGb);
  67. });
  68. }
  69. [Fact]
  70. public void Routable_interface_wins_over_loopback_and_docker_bridge() =>
  71. Assert.Equal("192.168.1.20", SystemFactsParser.Parse(LinuxSnapshot()).Ip);
  72. [Fact]
  73. public void Falls_back_to_a_real_interface_when_none_advertises_a_gateway() {
  74. RawSystemSnapshot snapshot = LinuxSnapshot() with {
  75. Nics = [
  76. new NicFact("lo", true, true, false, "127.0.0.1"),
  77. new NicFact("docker0", true, false, false, "172.17.0.1"),
  78. new NicFact("eno1", true, false, false, "192.168.1.20")
  79. ]
  80. };
  81. Assert.Equal("192.168.1.20", SystemFactsParser.Parse(snapshot).Ip);
  82. }
  83. [Theory]
  84. [InlineData("QEMU", "Standard PC (i440FX + PIIX, 1996)", "vm")]
  85. [InlineData("VMware, Inc.", "VMware Virtual Platform", "vm")]
  86. [InlineData("Microsoft Corporation", "Virtual Machine", "vm")]
  87. [InlineData("innotek GmbH", "VirtualBox", "vm")]
  88. [InlineData("Dell Inc.", "PowerEdge R730", "baremetal")]
  89. [InlineData("Supermicro", "X11SSH-F", "baremetal")]
  90. public void Virtualisation_is_read_from_dmi(string vendor, string product, string expected) {
  91. RawSystemSnapshot snapshot = LinuxSnapshot(dmiVendor: vendor, dmiProduct: product);
  92. Assert.Equal(expected, SystemFactsParser.Parse(snapshot).Type);
  93. }
  94. [Fact]
  95. public void A_container_is_detected_from_its_cgroup() {
  96. RawSystemSnapshot snapshot = LinuxSnapshot(cgroup: Fixture.Read("linux-cgroup-container"));
  97. Assert.Equal("container", SystemFactsParser.Parse(snapshot).Type);
  98. }
  99. [Fact]
  100. public void A_container_does_not_claim_the_host_disks_it_can_see() {
  101. // /sys/block inside a container shows the machine underneath it.
  102. RawSystemSnapshot snapshot = LinuxSnapshot(cgroup: Fixture.Read("linux-cgroup-container"));
  103. SystemFacts facts = SystemFactsParser.Parse(snapshot);
  104. Assert.Equal("container", facts.Type);
  105. Assert.Empty(facts.Drives);
  106. }
  107. [Fact]
  108. public void A_container_is_detected_from_the_dockerenv_marker() {
  109. RawSystemSnapshot snapshot = LinuxSnapshot() with { DockerEnvPresent = true };
  110. Assert.Equal("container", SystemFactsParser.Parse(snapshot).Type);
  111. }
  112. [Fact]
  113. public void Type_is_one_of_the_values_the_schema_accepts() {
  114. SystemFacts facts = SystemFactsParser.Parse(LinuxSnapshot());
  115. Assert.Contains(facts.Type, SystemResource.ValidSystemTypes);
  116. }
  117. [Fact]
  118. public void Macos_reads_its_identity_out_of_ioreg() {
  119. var uuid = MacSystemProbe.ParsePlatformUuid(Fixture.Read("macos-ioreg.txt"));
  120. Assert.Equal("5C8E1F2A-3B4D-5E6F-7A8B-9C0D1E2F3A4B", uuid);
  121. }
  122. [Fact]
  123. public void Macos_host_maps_without_disks_rather_than_guessing_at_them() {
  124. var snapshot = new RawSystemSnapshot {
  125. Hostname = "tims-macbook-pro.local",
  126. Cores = 14,
  127. OsName = "macOS 15.7.3",
  128. MemoryBytes = 51_539_607_552,
  129. PlatformUuid = "5C8E1F2A-3B4D-5E6F-7A8B-9C0D1E2F3A4B",
  130. Nics = [new NicFact("en0", true, false, true, "10.0.20.157")]
  131. };
  132. SystemResource resource = SystemResourceMapper.ToResource(SystemFactsParser.Parse(snapshot));
  133. Assert.Equal("tims-macbook-pro", resource.Name);
  134. Assert.Equal("macOS 15.7.3", resource.Os);
  135. Assert.Equal(48, resource.Ram);
  136. Assert.Equal("baremetal", resource.Type);
  137. Assert.Null(resource.Drives);
  138. }
  139. [Fact]
  140. public void A_hypervisor_flag_on_macos_means_the_host_is_a_guest() {
  141. var snapshot = new RawSystemSnapshot {
  142. Hostname = "vm",
  143. Cores = 4,
  144. OsName = "macOS 15.7.3",
  145. MemoryBytes = 8_589_934_592,
  146. HypervisorPresent = true
  147. };
  148. Assert.Equal("vm", SystemFactsParser.Parse(snapshot).Type);
  149. }
  150. [Fact]
  151. public void An_explicit_name_beats_the_hostname() {
  152. SystemFacts facts = SystemFactsParser.Parse(LinuxSnapshot());
  153. Assert.Equal("storage-01", SystemResourceMapper.ToResource(facts, "storage-01").Name);
  154. }
  155. [Fact]
  156. public void Output_conforms_to_the_published_schema() {
  157. SystemFacts facts = SystemFactsParser.Parse(LinuxSnapshot());
  158. Fixture.AssertConformsToSchema(
  159. DiscoveryDocument.ToYaml([SystemResourceMapper.ToResource(facts)]));
  160. }
  161. }