feat(task): auto-inject scheduling params into script template via scheduling_map

Add scheduling_map field to ParameterSchema so Application creators can
declare that a parameter (e.g. NP) maps to a scheduling field (e.g. cpus).
The backend auto-injects the scheduling value into script template variables
before rendering, eliminating duplicate user input. The frontend hides
mapped parameters from the form and injects their values on submit.
This commit is contained in:
dailz
2026-04-22 10:26:52 +08:00
parent 435ab285c1
commit 5591b67f75
9 changed files with 206 additions and 2 deletions

View File

@@ -0,0 +1,72 @@
package service
import (
"testing"
"gcy_hpc_server/internal/model"
)
func strPtr(v string) *string { return &v }
func TestResolveSchedulingMap(t *testing.T) {
cpus := int32Ptr(8)
memPerNode := int64Ptr(4096)
memPerCpu := int64Ptr(512)
nodes := strPtr("2-4")
tasks := int32Ptr(4)
cpusPerTask := int32Ptr(2)
timeLimit := int32Ptr(60)
qos := strPtr("high")
task := &model.Task{
Partition: "gpu",
Cpus: cpus,
MemoryPerNode: memPerNode,
MemoryPerCpu: memPerCpu,
Nodes: nodes,
Tasks: tasks,
CpusPerTask: cpusPerTask,
TimeLimit: timeLimit,
QOS: qos,
}
tests := []struct {
field string
want string
}{
{"cpus", "8"},
{"memory_per_node", "4096"},
{"memory_per_cpu", "512"},
{"nodes", "2-4"},
{"tasks", "4"},
{"cpus_per_task", "2"},
{"partition", "gpu"},
{"time_limit", "60"},
{"qos", "high"},
{"unknown_field", ""},
}
for _, tt := range tests {
t.Run(tt.field, func(t *testing.T) {
got := ResolveSchedulingMap(tt.field, task)
if got != tt.want {
t.Errorf("ResolveSchedulingMap(%q) = %q, want %q", tt.field, got, tt.want)
}
})
}
}
func TestResolveSchedulingMap_NilFields(t *testing.T) {
// All scheduling fields are nil/empty — should return empty strings
task := &model.Task{}
for _, field := range []string{"cpus", "memory_per_node", "memory_per_cpu", "nodes", "tasks", "cpus_per_task", "time_limit", "qos"} {
got := ResolveSchedulingMap(field, task)
if got != "" {
t.Errorf("ResolveSchedulingMap(%q) with nil fields = %q, want empty", field, got)
}
}
// partition is a plain string, not a pointer — empty string is the zero value
if got := ResolveSchedulingMap("partition", task); got != "" {
t.Errorf("ResolveSchedulingMap(partition) = %q, want empty", got)
}
}