feat: add standalone server topology view
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package topology
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.mchus.pro/mchus/logpile/internal/exporter"
|
||||
"git.mchus.pro/mchus/logpile/internal/models"
|
||||
)
|
||||
|
||||
func intp(v int) *int { return &v }
|
||||
|
||||
func TestBuildDistinguishesNUMAZeroFromUnknown(t *testing.T) {
|
||||
snapshot := &exporter.ReanimatorExport{Hardware: exporter.ReanimatorHardware{
|
||||
Board: exporter.ReanimatorBoard{SerialNumber: "SN1"},
|
||||
CPUs: []exporter.ReanimatorCPU{{Socket: 0}, {Socket: 1}},
|
||||
PCIeDevices: []exporter.ReanimatorPCIe{
|
||||
{Slot: "0000:01:00.0", DeviceClass: "VideoController", Model: "GPU A", NUMANode: intp(0)},
|
||||
{Slot: "0000:02:00.0", DeviceClass: "NetworkController", Model: "NIC A", NUMANode: nil},
|
||||
},
|
||||
}}
|
||||
doc := Build(snapshot, nil)
|
||||
var gpuAttached, nicAttached bool
|
||||
for _, e := range doc.Edges {
|
||||
gpuAttached = gpuAttached || (e.From == "cpu:0" && e.To == "gpu:0000:01:00.0")
|
||||
nicAttached = nicAttached || strings.Contains(e.To, "nic:")
|
||||
}
|
||||
if !gpuAttached {
|
||||
t.Fatal("NUMA node 0 GPU was not attached to CPU 0")
|
||||
}
|
||||
if nicAttached {
|
||||
t.Fatal("unknown-affinity NIC must not be attached")
|
||||
}
|
||||
body, err := json.Marshal(doc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(body), `"numa_node":0`) {
|
||||
t.Fatalf("topology JSON lost NUMA zero: %s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUsesBeeStaticEvidence(t *testing.T) {
|
||||
snapshot := &exporter.ReanimatorExport{Hardware: exporter.ReanimatorHardware{
|
||||
Board: exporter.ReanimatorBoard{SerialNumber: "SN1"},
|
||||
CPUs: []exporter.ReanimatorCPU{{Socket: 0}, {Socket: 1}},
|
||||
Memory: []exporter.ReanimatorMemory{{Slot: "DIMM000(A)", SerialNumber: "M1", Status: "OK"}},
|
||||
Storage: []exporter.ReanimatorStorage{{Slot: "0:0:0:0", SerialNumber: "D1", Model: "Disk"}},
|
||||
PCIeDevices: []exporter.ReanimatorPCIe{
|
||||
{Slot: "0000:01:00.0", DeviceClass: "StorageController", NUMANode: intp(0)},
|
||||
{Slot: "0000:31:00.0", DeviceClass: "VideoController", Model: "GPU 0", NUMANode: intp(0)},
|
||||
{Slot: "0000:32:00.0", DeviceClass: "VideoController", Model: "GPU 1", NUMANode: intp(0)},
|
||||
},
|
||||
}}
|
||||
e := &models.TopologyEvidence{
|
||||
DIMMType17: "Memory Device\n Locator: DIMM000(A)\n Bank Locator: Node0_Channel0",
|
||||
StorageMap: "sda hctl=0:0:0:0 ctrl=0000:01:00.0",
|
||||
NVIDIAQueryCSV: "0, 0000:31:00.0\n1, 0000:32:00.0\n",
|
||||
NVIDIATopology: " GPU0 GPU1\nGPU0 X NV4\nGPU1 NV4 X\n",
|
||||
}
|
||||
doc := Build(snapshot, e)
|
||||
kinds := map[string]int{}
|
||||
for _, edge := range doc.Edges {
|
||||
kinds[edge.Kind]++
|
||||
}
|
||||
for _, kind := range []string{"memory", "storage", "nvlink"} {
|
||||
if kinds[kind] == 0 {
|
||||
t.Fatalf("missing %s edge: %+v", kind, doc.Edges)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderHTMLIsStaticAndEscapesLabels(t *testing.T) {
|
||||
body := string(RenderHTML(&models.TopologyDocument{Version: ContractVersion, Title: `<script>x</script>`, Nodes: []models.TopologyNode{{ID: "cpu:0", Kind: "cpu", Label: "CPU 0", Socket: intp(0)}}}))
|
||||
if strings.Contains(body, `<script>x</script>`) {
|
||||
t.Fatal("title was not escaped")
|
||||
}
|
||||
for _, forbidden := range []string{"setInterval(", "fetch(", "nvidia-smi"} {
|
||||
if strings.Contains(body, forbidden) {
|
||||
t.Fatalf("rendered page contains live behavior %q", forbidden)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user