296 lines
9.3 KiB
Go
296 lines
9.3 KiB
Go
package webui
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"bee/audit/internal/app"
|
|
"bee/audit/internal/platform"
|
|
)
|
|
|
|
func TestHandleAPISATRunDecodesBodyWithoutContentLength(t *testing.T) {
|
|
globalQueue.mu.Lock()
|
|
originalTasks := globalQueue.tasks
|
|
globalQueue.tasks = nil
|
|
globalQueue.mu.Unlock()
|
|
t.Cleanup(func() {
|
|
globalQueue.mu.Lock()
|
|
globalQueue.tasks = originalTasks
|
|
globalQueue.mu.Unlock()
|
|
})
|
|
|
|
h := &handler{opts: HandlerOptions{App: &app.App{}}}
|
|
req := httptest.NewRequest("POST", "/api/sat/cpu/run", strings.NewReader(`{"profile":"smoke"}`))
|
|
req.ContentLength = -1
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.handleAPISATRun("cpu").ServeHTTP(rec, req)
|
|
|
|
if rec.Code != 200 {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
globalQueue.mu.Lock()
|
|
defer globalQueue.mu.Unlock()
|
|
if len(globalQueue.tasks) != 1 {
|
|
t.Fatalf("tasks=%d want 1", len(globalQueue.tasks))
|
|
}
|
|
if got := globalQueue.tasks[0].params.BurnProfile; got != "smoke" {
|
|
t.Fatalf("burn profile=%q want smoke", got)
|
|
}
|
|
if got := globalQueue.tasks[0].Priority; got != taskPriorityValidate {
|
|
t.Fatalf("priority=%d want %d", got, taskPriorityValidate)
|
|
}
|
|
}
|
|
|
|
func TestHandleAPIBenchmarkNvidiaRunQueuesSelectedGPUs(t *testing.T) {
|
|
globalQueue.mu.Lock()
|
|
originalTasks := globalQueue.tasks
|
|
globalQueue.tasks = nil
|
|
globalQueue.mu.Unlock()
|
|
t.Cleanup(func() {
|
|
globalQueue.mu.Lock()
|
|
globalQueue.tasks = originalTasks
|
|
globalQueue.mu.Unlock()
|
|
})
|
|
prevList := apiListNvidiaGPUs
|
|
apiListNvidiaGPUs = func(_ *app.App) ([]platform.NvidiaGPU, error) {
|
|
return []platform.NvidiaGPU{
|
|
{Index: 1, Name: "NVIDIA H100 PCIe"},
|
|
{Index: 3, Name: "NVIDIA H100 PCIe"},
|
|
}, nil
|
|
}
|
|
t.Cleanup(func() { apiListNvidiaGPUs = prevList })
|
|
|
|
h := &handler{opts: HandlerOptions{App: &app.App{}}}
|
|
req := httptest.NewRequest("POST", "/api/bee-bench/nvidia/perf/run", strings.NewReader(`{"profile":"standard","gpu_indices":[1,3],"run_nccl":false}`))
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.handleAPIBenchmarkNvidiaRun(rec, req)
|
|
|
|
if rec.Code != 200 {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
globalQueue.mu.Lock()
|
|
defer globalQueue.mu.Unlock()
|
|
if len(globalQueue.tasks) != 1 {
|
|
t.Fatalf("tasks=%d want 1", len(globalQueue.tasks))
|
|
}
|
|
task := globalQueue.tasks[0]
|
|
if task.Target != "nvidia-bench-perf" {
|
|
t.Fatalf("target=%q want nvidia-bench-perf", task.Target)
|
|
}
|
|
if got := task.params.GPUIndices; len(got) != 2 || got[0] != 1 || got[1] != 3 {
|
|
t.Fatalf("gpu indices=%v want [1 3]", got)
|
|
}
|
|
if task.params.RunNCCL {
|
|
t.Fatal("RunNCCL should reflect explicit false from request")
|
|
}
|
|
if task.Priority != taskPriorityBenchmark {
|
|
t.Fatalf("priority=%d want %d", task.Priority, taskPriorityBenchmark)
|
|
}
|
|
}
|
|
|
|
func TestHandleAPIBenchmarkNvidiaRunSplitsMixedGPUModels(t *testing.T) {
|
|
globalQueue.mu.Lock()
|
|
originalTasks := globalQueue.tasks
|
|
globalQueue.tasks = nil
|
|
globalQueue.mu.Unlock()
|
|
t.Cleanup(func() {
|
|
globalQueue.mu.Lock()
|
|
globalQueue.tasks = originalTasks
|
|
globalQueue.mu.Unlock()
|
|
})
|
|
prevList := apiListNvidiaGPUs
|
|
apiListNvidiaGPUs = func(_ *app.App) ([]platform.NvidiaGPU, error) {
|
|
return []platform.NvidiaGPU{
|
|
{Index: 0, Name: "NVIDIA H100 PCIe"},
|
|
{Index: 1, Name: "NVIDIA H100 PCIe"},
|
|
{Index: 2, Name: "NVIDIA H200 NVL"},
|
|
}, nil
|
|
}
|
|
t.Cleanup(func() { apiListNvidiaGPUs = prevList })
|
|
|
|
h := &handler{opts: HandlerOptions{App: &app.App{}}}
|
|
req := httptest.NewRequest("POST", "/api/bee-bench/nvidia/perf/run", strings.NewReader(`{"profile":"standard","gpu_indices":[0,1,2],"run_nccl":false}`))
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.handleAPIBenchmarkNvidiaRun(rec, req)
|
|
|
|
if rec.Code != 200 {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
var resp taskRunResponse
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
|
t.Fatalf("decode response: %v", err)
|
|
}
|
|
if len(resp.TaskIDs) != 2 {
|
|
t.Fatalf("task_ids=%v want 2 items", resp.TaskIDs)
|
|
}
|
|
globalQueue.mu.Lock()
|
|
defer globalQueue.mu.Unlock()
|
|
if len(globalQueue.tasks) != 2 {
|
|
t.Fatalf("tasks=%d want 2", len(globalQueue.tasks))
|
|
}
|
|
if got := globalQueue.tasks[0].params.GPUIndices; len(got) != 2 || got[0] != 0 || got[1] != 1 {
|
|
t.Fatalf("task[0] gpu indices=%v want [0 1]", got)
|
|
}
|
|
if got := globalQueue.tasks[1].params.GPUIndices; len(got) != 1 || got[0] != 2 {
|
|
t.Fatalf("task[1] gpu indices=%v want [2]", got)
|
|
}
|
|
if got := globalQueue.tasks[0].Priority; got != taskPriorityBenchmark {
|
|
t.Fatalf("task[0] priority=%d want %d", got, taskPriorityBenchmark)
|
|
}
|
|
if got := globalQueue.tasks[1].Priority; got != taskPriorityBenchmark {
|
|
t.Fatalf("task[1] priority=%d want %d", got, taskPriorityBenchmark)
|
|
}
|
|
}
|
|
|
|
func TestHandleAPIBenchmarkPowerFitRampQueuesBenchmarkPowerFitTasks(t *testing.T) {
|
|
globalQueue.mu.Lock()
|
|
originalTasks := globalQueue.tasks
|
|
globalQueue.tasks = nil
|
|
globalQueue.mu.Unlock()
|
|
t.Cleanup(func() {
|
|
globalQueue.mu.Lock()
|
|
globalQueue.tasks = originalTasks
|
|
globalQueue.mu.Unlock()
|
|
})
|
|
prevList := apiListNvidiaGPUs
|
|
apiListNvidiaGPUs = func(_ *app.App) ([]platform.NvidiaGPU, error) {
|
|
return []platform.NvidiaGPU{
|
|
{Index: 0, Name: "NVIDIA H100 PCIe"},
|
|
{Index: 1, Name: "NVIDIA H100 PCIe"},
|
|
{Index: 2, Name: "NVIDIA H100 PCIe"},
|
|
}, nil
|
|
}
|
|
t.Cleanup(func() { apiListNvidiaGPUs = prevList })
|
|
|
|
h := &handler{opts: HandlerOptions{App: &app.App{}}}
|
|
req := httptest.NewRequest("POST", "/api/bee-bench/nvidia/power/run", strings.NewReader(`{"profile":"standard","gpu_indices":[0,1,2],"ramp_up":true}`))
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.handleAPIBenchmarkNvidiaRunKind("nvidia-bench-power").ServeHTTP(rec, req)
|
|
|
|
if rec.Code != 200 {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
globalQueue.mu.Lock()
|
|
defer globalQueue.mu.Unlock()
|
|
if len(globalQueue.tasks) != 3 {
|
|
t.Fatalf("tasks=%d want 3", len(globalQueue.tasks))
|
|
}
|
|
for i, task := range globalQueue.tasks {
|
|
if task.Target != "nvidia-bench-power" {
|
|
t.Fatalf("task[%d] target=%q", i, task.Target)
|
|
}
|
|
if task.Priority != taskPriorityBenchmark {
|
|
t.Fatalf("task[%d] priority=%d want %d", i, task.Priority, taskPriorityBenchmark)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHandleAPISATRunSplitsMixedNvidiaTaskSet(t *testing.T) {
|
|
globalQueue.mu.Lock()
|
|
originalTasks := globalQueue.tasks
|
|
globalQueue.tasks = nil
|
|
globalQueue.mu.Unlock()
|
|
t.Cleanup(func() {
|
|
globalQueue.mu.Lock()
|
|
globalQueue.tasks = originalTasks
|
|
globalQueue.mu.Unlock()
|
|
})
|
|
prevList := apiListNvidiaGPUs
|
|
apiListNvidiaGPUs = func(_ *app.App) ([]platform.NvidiaGPU, error) {
|
|
return []platform.NvidiaGPU{
|
|
{Index: 0, Name: "NVIDIA H100 PCIe"},
|
|
{Index: 1, Name: "NVIDIA H100 PCIe"},
|
|
{Index: 2, Name: "NVIDIA H200 NVL"},
|
|
}, nil
|
|
}
|
|
t.Cleanup(func() { apiListNvidiaGPUs = prevList })
|
|
|
|
h := &handler{opts: HandlerOptions{App: &app.App{}}}
|
|
req := httptest.NewRequest("POST", "/api/sat/nvidia-targeted-power/run", strings.NewReader(`{"profile":"acceptance","gpu_indices":[0,1,2]}`))
|
|
rec := httptest.NewRecorder()
|
|
|
|
h.handleAPISATRun("nvidia-targeted-power").ServeHTTP(rec, req)
|
|
|
|
if rec.Code != 200 {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
globalQueue.mu.Lock()
|
|
defer globalQueue.mu.Unlock()
|
|
if len(globalQueue.tasks) != 2 {
|
|
t.Fatalf("tasks=%d want 2", len(globalQueue.tasks))
|
|
}
|
|
if got := globalQueue.tasks[0].params.GPUIndices; len(got) != 2 || got[0] != 0 || got[1] != 1 {
|
|
t.Fatalf("task[0] gpu indices=%v want [0 1]", got)
|
|
}
|
|
if got := globalQueue.tasks[1].params.GPUIndices; len(got) != 1 || got[0] != 2 {
|
|
t.Fatalf("task[1] gpu indices=%v want [2]", got)
|
|
}
|
|
if got := globalQueue.tasks[0].Priority; got != taskPriorityValidate {
|
|
t.Fatalf("task[0] priority=%d want %d", got, taskPriorityValidate)
|
|
}
|
|
if got := globalQueue.tasks[1].Priority; got != taskPriorityValidate {
|
|
t.Fatalf("task[1] priority=%d want %d", got, taskPriorityValidate)
|
|
}
|
|
}
|
|
|
|
func TestDefaultTaskPriorityOrder(t *testing.T) {
|
|
got := []int{
|
|
defaultTaskPriority("install-to-ram", taskParams{}),
|
|
defaultTaskPriority("audit", taskParams{}),
|
|
defaultTaskPriority("cpu", taskParams{}),
|
|
defaultTaskPriority("cpu", taskParams{StressMode: true}),
|
|
defaultTaskPriority("nvidia-stress", taskParams{}),
|
|
defaultTaskPriority("nvidia-bench-perf", taskParams{}),
|
|
defaultTaskPriority("nvidia-bench-power", taskParams{}),
|
|
}
|
|
want := []int{
|
|
taskPriorityInstallToRAM,
|
|
taskPriorityAudit,
|
|
taskPriorityValidate,
|
|
taskPriorityValidateStress,
|
|
taskPriorityBurn,
|
|
taskPriorityBenchmark,
|
|
taskPriorityBenchmark,
|
|
}
|
|
for i := range want {
|
|
if got[i] != want[i] {
|
|
t.Fatalf("priority[%d]=%d want %d", i, got[i], want[i])
|
|
}
|
|
}
|
|
if !(got[0] > got[1] && got[1] > got[2] && got[2] > got[3] && got[3] > got[4] && got[4] > got[5] && got[5] == got[6]) {
|
|
t.Fatalf("priority order=%v", got)
|
|
}
|
|
}
|
|
|
|
func TestPushFanRingsTracksByNameAndCarriesForwardMissingSamples(t *testing.T) {
|
|
h := &handler{}
|
|
h.pushFanRings([]platform.FanReading{
|
|
{Name: "FAN_A", RPM: 4200},
|
|
{Name: "FAN_B", RPM: 5100},
|
|
})
|
|
h.pushFanRings([]platform.FanReading{
|
|
{Name: "FAN_B", RPM: 5200},
|
|
})
|
|
|
|
if len(h.fanNames) != 2 || h.fanNames[0] != "FAN_A" || h.fanNames[1] != "FAN_B" {
|
|
t.Fatalf("fanNames=%v", h.fanNames)
|
|
}
|
|
aVals, _ := h.ringFans[0].snapshot()
|
|
bVals, _ := h.ringFans[1].snapshot()
|
|
if len(aVals) != 2 || len(bVals) != 2 {
|
|
t.Fatalf("fan ring lengths: A=%d B=%d", len(aVals), len(bVals))
|
|
}
|
|
if aVals[1] != 4200 {
|
|
t.Fatalf("FAN_A should carry forward last value, got %v", aVals)
|
|
}
|
|
if bVals[1] != 5200 {
|
|
t.Fatalf("FAN_B should use latest sampled value, got %v", bVals)
|
|
}
|
|
}
|