feat: 添加 Diag/Ping/Licenses/Reconfigure 类型和对应服务
包含 StatsMsg(含调度和回填统计)、ControllerPing、License 等类型。实现 4 个服务:DiagService.GetDiag、PingService.Ping、LicensesService.GetLicenses、ReconfigureService.Reconfigure。 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
67
internal/slurm/slurm_diag.go
Normal file
67
internal/slurm/slurm_diag.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package slurm
|
||||
|
||||
import "context"
|
||||
|
||||
// GetDiag returns slurm diagnostics information.
|
||||
func (s *DiagService) GetDiag(ctx context.Context) (*OpenapiDiagResp, *Response, error) {
|
||||
path := "slurm/v0.0.40/diag"
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var result OpenapiDiagResp
|
||||
resp, err := s.client.Do(ctx, req, &result)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return &result, resp, nil
|
||||
}
|
||||
|
||||
// Ping returns slurm controller ping information.
|
||||
func (s *PingService) Ping(ctx context.Context) (*OpenapiPingArrayResp, *Response, error) {
|
||||
path := "slurm/v0.0.40/ping"
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var result OpenapiPingArrayResp
|
||||
resp, err := s.client.Do(ctx, req, &result)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return &result, resp, nil
|
||||
}
|
||||
|
||||
// GetLicenses returns slurm license information.
|
||||
func (s *LicensesService) GetLicenses(ctx context.Context) (*OpenapiLicensesResp, *Response, error) {
|
||||
path := "slurm/v0.0.40/licenses"
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var result OpenapiLicensesResp
|
||||
resp, err := s.client.Do(ctx, req, &result)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return &result, resp, nil
|
||||
}
|
||||
|
||||
// Reconfigure requests slurm reconfigure.
|
||||
func (s *ReconfigureService) Reconfigure(ctx context.Context) (*OpenapiResp, *Response, error) {
|
||||
path := "slurm/v0.0.40/reconfigure"
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var result OpenapiResp
|
||||
resp, err := s.client.Do(ctx, req, &result)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return &result, resp, nil
|
||||
}
|
||||
162
internal/slurm/slurm_diag_test.go
Normal file
162
internal/slurm/slurm_diag_test.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package slurm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDiagService_GetDiag(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/diag", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"statistics": {"parts": 1}, "meta": {"plugin": {"type": "openapi/slurmctld"}}}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
resp, _, err := client.Diag.GetDiag(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatal("expected non-nil response")
|
||||
}
|
||||
if resp.Statistics == nil {
|
||||
t.Fatal("expected non-nil statistics")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiagService_GetDiag_Error(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/diag", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
_, _, err := client.Diag.GetDiag(context.Background())
|
||||
if err == nil {
|
||||
t.Fatal("expected error for 500 response")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "500") {
|
||||
t.Errorf("expected error to contain 500, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPingService_Ping(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/ping", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"pings": [{"hostname": "slurmctl", "pinged": "UP", "latency": 100, "mode": "primary"}]}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
resp, _, err := client.Ping.Ping(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatal("expected non-nil response")
|
||||
}
|
||||
if len(resp.Pings) != 1 {
|
||||
t.Errorf("expected 1 ping, got %d", len(resp.Pings))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPingService_Ping_Error(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/ping", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
fmt.Fprint(w, `{"errors": [{"error": "service unavailable"}]}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
_, _, err := client.Ping.Ping(context.Background())
|
||||
if err == nil {
|
||||
t.Fatal("expected error for 503 response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicensesService_GetLicenses(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/licenses", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"licenses": [{"LicenseName": "matlab", "Total": 10, "Used": 3, "Free": 7, "Remote": false}]}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
resp, _, err := client.Licenses.GetLicenses(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatal("expected non-nil response")
|
||||
}
|
||||
if len(resp.Licenses) != 1 {
|
||||
t.Errorf("expected 1 license, got %d", len(resp.Licenses))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicensesService_GetLicenses_Error(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/licenses", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
_, _, err := client.Licenses.GetLicenses(context.Background())
|
||||
if err == nil {
|
||||
t.Fatal("expected error for 500 response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconfigureService_Reconfigure(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/reconfigure", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
resp, _, err := client.Reconfigure.Reconfigure(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatal("expected non-nil response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconfigureService_Reconfigure_Error(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/slurm/v0.0.40/reconfigure", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
client, _ := NewClient(server.URL, nil)
|
||||
_, _, err := client.Reconfigure.Reconfigure(context.Background())
|
||||
if err == nil {
|
||||
t.Fatal("expected error for 500 response")
|
||||
}
|
||||
}
|
||||
149
internal/slurm/types_diag.go
Normal file
149
internal/slurm/types_diag.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package slurm
|
||||
|
||||
// ScheduleExitFields represents schedule exit fields (v0.0.40_schedule_exit_fields).
|
||||
type ScheduleExitFields struct {
|
||||
EndJobQueue *int32 `json:"end_job_queue,omitempty"`
|
||||
DefaultQueueDepth *int32 `json:"default_queue_depth,omitempty"`
|
||||
MaxJobStart *int32 `json:"max_job_start,omitempty"`
|
||||
MaxRpcCnt *int32 `json:"max_rpc_cnt,omitempty"`
|
||||
MaxSchedTime *int32 `json:"max_sched_time,omitempty"`
|
||||
Licenses *int32 `json:"licenses,omitempty"`
|
||||
}
|
||||
|
||||
// BfExitFields represents backfill exit fields (v0.0.40_bf_exit_fields).
|
||||
type BfExitFields struct {
|
||||
EndJobQueue *int32 `json:"end_job_queue,omitempty"`
|
||||
BfMaxJobStart *int32 `json:"bf_max_job_start,omitempty"`
|
||||
BfMaxJobTest *int32 `json:"bf_max_job_test,omitempty"`
|
||||
BfMaxTime *int32 `json:"bf_max_time,omitempty"`
|
||||
BfNodeSpaceSize *int32 `json:"bf_node_space_size,omitempty"`
|
||||
StateChanged *int32 `json:"state_changed,omitempty"`
|
||||
}
|
||||
|
||||
// StatsMsgRpcsByTypeItem represents a single RPC stats by message type entry.
|
||||
type StatsMsgRpcsByTypeItem struct {
|
||||
MessageType *string `json:"message_type,omitempty"`
|
||||
TypeID *int32 `json:"type_id,omitempty"`
|
||||
Count *int64 `json:"count,omitempty"`
|
||||
AverageTime *int64 `json:"average_time,omitempty"`
|
||||
TotalTime *int64 `json:"total_time,omitempty"`
|
||||
}
|
||||
|
||||
// StatsMsgRpcsByType represents RPC stats by message type (v0.0.40_stats_msg_rpcs_by_type).
|
||||
type StatsMsgRpcsByType []StatsMsgRpcsByTypeItem
|
||||
|
||||
// StatsMsgRpcsByUserItem represents a single RPC stats by user entry.
|
||||
type StatsMsgRpcsByUserItem struct {
|
||||
User *string `json:"user,omitempty"`
|
||||
UserID *int32 `json:"user_id,omitempty"`
|
||||
Count *int64 `json:"count,omitempty"`
|
||||
AverageTime *int64 `json:"average_time,omitempty"`
|
||||
TotalTime *int64 `json:"total_time,omitempty"`
|
||||
}
|
||||
|
||||
// StatsMsgRpcsByUser represents RPC stats by user (v0.0.40_stats_msg_rpcs_by_user).
|
||||
type StatsMsgRpcsByUser []StatsMsgRpcsByUserItem
|
||||
|
||||
// StatsMsg represents Slurm statistics message (v0.0.40_stats_msg).
|
||||
type StatsMsg struct {
|
||||
PartsPacked *int32 `json:"parts_packed,omitempty"`
|
||||
ReqTime *Uint64NoVal `json:"req_time,omitempty"`
|
||||
ReqTimeStart *Uint64NoVal `json:"req_time_start,omitempty"`
|
||||
ServerThreadCount *int32 `json:"server_thread_count,omitempty"`
|
||||
AgentQueueSize *int32 `json:"agent_queue_size,omitempty"`
|
||||
AgentCount *int32 `json:"agent_count,omitempty"`
|
||||
AgentThreadCount *int32 `json:"agent_thread_count,omitempty"`
|
||||
DbdAgentQueueSize *int32 `json:"dbd_agent_queue_size,omitempty"`
|
||||
GettimeofdayLatency *int32 `json:"gettimeofday_latency,omitempty"`
|
||||
ScheduleCycleMax *int32 `json:"schedule_cycle_max,omitempty"`
|
||||
ScheduleCycleLast *int32 `json:"schedule_cycle_last,omitempty"`
|
||||
ScheduleCycleTotal *int32 `json:"schedule_cycle_total,omitempty"`
|
||||
ScheduleCycleMean *int64 `json:"schedule_cycle_mean,omitempty"`
|
||||
ScheduleCycleMeanDepth *int64 `json:"schedule_cycle_mean_depth,omitempty"`
|
||||
ScheduleCyclePerMinute *int64 `json:"schedule_cycle_per_minute,omitempty"`
|
||||
ScheduleQueueLength *int32 `json:"schedule_queue_length,omitempty"`
|
||||
ScheduleExit *ScheduleExitFields `json:"schedule_exit,omitempty"`
|
||||
JobsSubmitted *int32 `json:"jobs_submitted,omitempty"`
|
||||
JobsStarted *int32 `json:"jobs_started,omitempty"`
|
||||
JobsCompleted *int32 `json:"jobs_completed,omitempty"`
|
||||
JobsCanceled *int32 `json:"jobs_canceled,omitempty"`
|
||||
JobsFailed *int32 `json:"jobs_failed,omitempty"`
|
||||
JobsPending *int32 `json:"jobs_pending,omitempty"`
|
||||
JobsRunning *int32 `json:"jobs_running,omitempty"`
|
||||
JobStatesTs *Uint64NoVal `json:"job_states_ts,omitempty"`
|
||||
BfBackfilledJobs *int32 `json:"bf_backfilled_jobs,omitempty"`
|
||||
BfLastBackfilledJobs *int32 `json:"bf_last_backfilled_jobs,omitempty"`
|
||||
BfBackfilledHetJobs *int32 `json:"bf_backfilled_het_jobs,omitempty"`
|
||||
BfCycleCounter *int32 `json:"bf_cycle_counter,omitempty"`
|
||||
BfCycleMean *int64 `json:"bf_cycle_mean,omitempty"`
|
||||
BfDepthMean *int64 `json:"bf_depth_mean,omitempty"`
|
||||
BfDepthMeanTry *int64 `json:"bf_depth_mean_try,omitempty"`
|
||||
BfCycleSum *int64 `json:"bf_cycle_sum,omitempty"`
|
||||
BfCycleLast *int32 `json:"bf_cycle_last,omitempty"`
|
||||
BfLastDepth *int32 `json:"bf_last_depth,omitempty"`
|
||||
BfLastDepthTry *int32 `json:"bf_last_depth_try,omitempty"`
|
||||
BfDepthSum *int32 `json:"bf_depth_sum,omitempty"`
|
||||
BfDepthTrySum *int32 `json:"bf_depth_try_sum,omitempty"`
|
||||
BfQueueLen *int32 `json:"bf_queue_len,omitempty"`
|
||||
BfQueueLenMean *int64 `json:"bf_queue_len_mean,omitempty"`
|
||||
BfQueueLenSum *int32 `json:"bf_queue_len_sum,omitempty"`
|
||||
BfTableSize *int32 `json:"bf_table_size,omitempty"`
|
||||
BfTableSizeMean *int64 `json:"bf_table_size_mean,omitempty"`
|
||||
BfWhenLastCycle *Uint64NoVal `json:"bf_when_last_cycle,omitempty"`
|
||||
BfActive *bool `json:"bf_active,omitempty"`
|
||||
BfExit *BfExitFields `json:"bf_exit,omitempty"`
|
||||
RpcsByMessageType *StatsMsgRpcsByType `json:"rpcs_by_message_type,omitempty"`
|
||||
RpcsByUser *StatsMsgRpcsByUser `json:"rpcs_by_user,omitempty"`
|
||||
}
|
||||
|
||||
// ControllerPing represents a controller ping result (v0.0.40_controller_ping).
|
||||
type ControllerPing struct {
|
||||
Hostname *string `json:"hostname,omitempty"`
|
||||
Pinged *string `json:"pinged,omitempty"`
|
||||
Latency *int64 `json:"latency,omitempty"`
|
||||
Mode *string `json:"mode,omitempty"`
|
||||
}
|
||||
|
||||
// ControllerPingArray represents an array of controller ping results (v0.0.40_controller_ping_array).
|
||||
type ControllerPingArray []ControllerPing
|
||||
|
||||
// License represents Slurm license information (v0.0.40_license).
|
||||
type License struct {
|
||||
LicenseName *string `json:"LicenseName,omitempty"`
|
||||
Total *int32 `json:"Total,omitempty"`
|
||||
Used *int32 `json:"Used,omitempty"`
|
||||
Free *int32 `json:"Free,omitempty"`
|
||||
Remote *bool `json:"Remote,omitempty"`
|
||||
Reserved *int32 `json:"Reserved,omitempty"`
|
||||
LastConsumed *int32 `json:"LastConsumed,omitempty"`
|
||||
LastDeficit *int32 `json:"LastDeficit,omitempty"`
|
||||
LastUpdate *int64 `json:"LastUpdate,omitempty"`
|
||||
}
|
||||
|
||||
// Licenses represents a list of licenses (v0.0.40_licenses).
|
||||
type Licenses []License
|
||||
|
||||
// OpenapiDiagResp represents the diag API response (v0.0.40_openapi_diag_resp).
|
||||
type OpenapiDiagResp struct {
|
||||
Statistics *StatsMsg `json:"statistics,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiPingArrayResp represents the ping API response (v0.0.40_openapi_ping_array_resp).
|
||||
type OpenapiPingArrayResp struct {
|
||||
Pings ControllerPingArray `json:"pings,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiLicensesResp represents the licenses API response (v0.0.40_openapi_licenses_resp).
|
||||
type OpenapiLicensesResp struct {
|
||||
Licenses Licenses `json:"licenses,omitempty"`
|
||||
LastUpdate *Uint64NoVal `json:"last_update,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
309
internal/slurm/types_diag_test.go
Normal file
309
internal/slurm/types_diag_test.go
Normal file
@@ -0,0 +1,309 @@
|
||||
package slurm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStatsMsgRoundTrip(t *testing.T) {
|
||||
orig := StatsMsg{
|
||||
PartsPacked: Ptr(int32(1)),
|
||||
ReqTime: &Uint64NoVal{Set: Ptr(true), Number: Ptr(int64(1700000000))},
|
||||
ReqTimeStart: &Uint64NoVal{Set: Ptr(true), Number: Ptr(int64(1699999999))},
|
||||
ServerThreadCount: Ptr(int32(4)),
|
||||
AgentQueueSize: Ptr(int32(0)),
|
||||
AgentCount: Ptr(int32(10)),
|
||||
AgentThreadCount: Ptr(int32(4)),
|
||||
DbdAgentQueueSize: Ptr(int32(0)),
|
||||
GettimeofdayLatency: Ptr(int32(1)),
|
||||
ScheduleCycleMax: Ptr(int32(100)),
|
||||
ScheduleCycleLast: Ptr(int32(5)),
|
||||
ScheduleCycleTotal: Ptr(int32(500)),
|
||||
ScheduleCycleMean: Ptr(int64(10)),
|
||||
ScheduleCycleMeanDepth: Ptr(int64(3)),
|
||||
ScheduleCyclePerMinute: Ptr(int64(60)),
|
||||
ScheduleQueueLength: Ptr(int32(42)),
|
||||
ScheduleExit: &ScheduleExitFields{
|
||||
EndJobQueue: Ptr(int32(1)),
|
||||
DefaultQueueDepth: Ptr(int32(100)),
|
||||
MaxJobStart: Ptr(int32(0)),
|
||||
MaxRpcCnt: Ptr(int32(0)),
|
||||
MaxSchedTime: Ptr(int32(0)),
|
||||
Licenses: Ptr(int32(0)),
|
||||
},
|
||||
JobsSubmitted: Ptr(int32(1000)),
|
||||
JobsStarted: Ptr(int32(900)),
|
||||
JobsCompleted: Ptr(int32(850)),
|
||||
JobsCanceled: Ptr(int32(20)),
|
||||
JobsFailed: Ptr(int32(5)),
|
||||
JobsPending: Ptr(int32(30)),
|
||||
JobsRunning: Ptr(int32(45)),
|
||||
JobStatesTs: &Uint64NoVal{Set: Ptr(true), Number: Ptr(int64(1700000000))},
|
||||
BfBackfilledJobs: Ptr(int32(200)),
|
||||
BfLastBackfilledJobs: Ptr(int32(5)),
|
||||
BfBackfilledHetJobs: Ptr(int32(0)),
|
||||
BfCycleCounter: Ptr(int32(500)),
|
||||
BfCycleMean: Ptr(int64(2)),
|
||||
BfDepthMean: Ptr(int64(10)),
|
||||
BfDepthMeanTry: Ptr(int64(8)),
|
||||
BfCycleSum: Ptr(int64(1000)),
|
||||
BfCycleLast: Ptr(int32(3)),
|
||||
BfLastDepth: Ptr(int32(15)),
|
||||
BfLastDepthTry: Ptr(int32(12)),
|
||||
BfDepthSum: Ptr(int32(5000)),
|
||||
BfDepthTrySum: Ptr(int32(4000)),
|
||||
BfQueueLen: Ptr(int32(30)),
|
||||
BfQueueLenMean: Ptr(int64(25)),
|
||||
BfQueueLenSum: Ptr(int32(15000)),
|
||||
BfTableSize: Ptr(int32(500)),
|
||||
BfTableSizeMean: Ptr(int64(450)),
|
||||
BfWhenLastCycle: &Uint64NoVal{Set: Ptr(true), Number: Ptr(int64(1700000050))},
|
||||
BfActive: Ptr(true),
|
||||
BfExit: &BfExitFields{
|
||||
EndJobQueue: Ptr(int32(0)),
|
||||
BfMaxJobStart: Ptr(int32(0)),
|
||||
BfMaxJobTest: Ptr(int32(0)),
|
||||
BfMaxTime: Ptr(int32(0)),
|
||||
BfNodeSpaceSize: Ptr(int32(0)),
|
||||
StateChanged: Ptr(int32(0)),
|
||||
},
|
||||
RpcsByMessageType: &StatsMsgRpcsByType{
|
||||
{MessageType: Ptr("REQUEST_JOB_INFO"), TypeID: Ptr(int32(2001)), Count: Ptr(int64(500)), AverageTime: Ptr(int64(10)), TotalTime: Ptr(int64(5000))},
|
||||
{MessageType: Ptr("REQUEST_NODE_INFO"), TypeID: Ptr(int32(2002)), Count: Ptr(int64(300)), AverageTime: Ptr(int64(5)), TotalTime: Ptr(int64(1500))},
|
||||
},
|
||||
RpcsByUser: &StatsMsgRpcsByUser{
|
||||
{User: Ptr("root"), UserID: Ptr(int32(0)), Count: Ptr(int64(100)), AverageTime: Ptr(int64(3)), TotalTime: Ptr(int64(300))},
|
||||
{User: Ptr("alice"), UserID: Ptr(int32(1001)), Count: Ptr(int64(50)), AverageTime: Ptr(int64(7)), TotalTime: Ptr(int64(350))},
|
||||
},
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded StatsMsg
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if *decoded.PartsPacked != *orig.PartsPacked {
|
||||
t.Errorf("PartsPacked: got %d, want %d", *decoded.PartsPacked, *orig.PartsPacked)
|
||||
}
|
||||
if *decoded.ScheduleExit.DefaultQueueDepth != *orig.ScheduleExit.DefaultQueueDepth {
|
||||
t.Errorf("ScheduleExit.DefaultQueueDepth: got %d, want %d", *decoded.ScheduleExit.DefaultQueueDepth, *orig.ScheduleExit.DefaultQueueDepth)
|
||||
}
|
||||
if *decoded.BfActive != *orig.BfActive {
|
||||
t.Errorf("BfActive: got %v, want %v", *decoded.BfActive, *orig.BfActive)
|
||||
}
|
||||
if len(*decoded.RpcsByMessageType) != len(*orig.RpcsByMessageType) {
|
||||
t.Errorf("RpcsByMessageType length: got %d, want %d", len(*decoded.RpcsByMessageType), len(*orig.RpcsByMessageType))
|
||||
}
|
||||
if len(*decoded.RpcsByUser) != len(*orig.RpcsByUser) {
|
||||
t.Errorf("RpcsByUser length: got %d, want %d", len(*decoded.RpcsByUser), len(*orig.RpcsByUser))
|
||||
}
|
||||
if *(*decoded.RpcsByMessageType)[0].MessageType != *(*orig.RpcsByMessageType)[0].MessageType {
|
||||
t.Errorf("RpcsByMessageType[0].MessageType: got %s, want %s", *(*decoded.RpcsByMessageType)[0].MessageType, *(*orig.RpcsByMessageType)[0].MessageType)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduleExitFieldsRoundTrip(t *testing.T) {
|
||||
orig := ScheduleExitFields{
|
||||
EndJobQueue: Ptr(int32(1)),
|
||||
DefaultQueueDepth: Ptr(int32(100)),
|
||||
MaxJobStart: Ptr(int32(50)),
|
||||
MaxRpcCnt: Ptr(int32(20)),
|
||||
MaxSchedTime: Ptr(int32(30)),
|
||||
Licenses: Ptr(int32(5)),
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded ScheduleExitFields
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if *decoded.EndJobQueue != *orig.EndJobQueue {
|
||||
t.Errorf("EndJobQueue: got %d, want %d", *decoded.EndJobQueue, *orig.EndJobQueue)
|
||||
}
|
||||
if *decoded.Licenses != *orig.Licenses {
|
||||
t.Errorf("Licenses: got %d, want %d", *decoded.Licenses, *orig.Licenses)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBfExitFieldsRoundTrip(t *testing.T) {
|
||||
orig := BfExitFields{
|
||||
EndJobQueue: Ptr(int32(1)),
|
||||
BfMaxJobStart: Ptr(int32(10)),
|
||||
BfMaxJobTest: Ptr(int32(100)),
|
||||
BfMaxTime: Ptr(int32(60)),
|
||||
BfNodeSpaceSize: Ptr(int32(500)),
|
||||
StateChanged: Ptr(int32(3)),
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded BfExitFields
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if *decoded.BfMaxJobTest != *orig.BfMaxJobTest {
|
||||
t.Errorf("BfMaxJobTest: got %d, want %d", *decoded.BfMaxJobTest, *orig.BfMaxJobTest)
|
||||
}
|
||||
if *decoded.StateChanged != *orig.StateChanged {
|
||||
t.Errorf("StateChanged: got %d, want %d", *decoded.StateChanged, *orig.StateChanged)
|
||||
}
|
||||
}
|
||||
|
||||
func TestControllerPingRoundTrip(t *testing.T) {
|
||||
orig := ControllerPing{
|
||||
Hostname: Ptr("controller1"),
|
||||
Pinged: Ptr("UP"),
|
||||
Latency: Ptr(int64(42)),
|
||||
Mode: Ptr("primary"),
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded ControllerPing
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if *decoded.Hostname != *orig.Hostname {
|
||||
t.Errorf("Hostname: got %s, want %s", *decoded.Hostname, *orig.Hostname)
|
||||
}
|
||||
if *decoded.Latency != *orig.Latency {
|
||||
t.Errorf("Latency: got %d, want %d", *decoded.Latency, *orig.Latency)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicenseRoundTrip(t *testing.T) {
|
||||
orig := License{
|
||||
LicenseName: Ptr("matlab"),
|
||||
Total: Ptr(int32(100)),
|
||||
Used: Ptr(int32(50)),
|
||||
Free: Ptr(int32(50)),
|
||||
Remote: Ptr(false),
|
||||
Reserved: Ptr(int32(10)),
|
||||
LastConsumed: Ptr(int32(45)),
|
||||
LastDeficit: Ptr(int32(0)),
|
||||
LastUpdate: Ptr(int64(1700000000)),
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded License
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if *decoded.LicenseName != *orig.LicenseName {
|
||||
t.Errorf("LicenseName: got %s, want %s", *decoded.LicenseName, *orig.LicenseName)
|
||||
}
|
||||
if *decoded.Total != *orig.Total {
|
||||
t.Errorf("Total: got %d, want %d", *decoded.Total, *orig.Total)
|
||||
}
|
||||
if *decoded.Remote != *orig.Remote {
|
||||
t.Errorf("Remote: got %v, want %v", *decoded.Remote, *orig.Remote)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenapiDiagRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiDiagResp{
|
||||
Statistics: &StatsMsg{
|
||||
PartsPacked: Ptr(int32(1)),
|
||||
ServerThreadCount: Ptr(int32(4)),
|
||||
AgentCount: Ptr(int32(10)),
|
||||
JobsRunning: Ptr(int32(45)),
|
||||
BfActive: Ptr(true),
|
||||
},
|
||||
Meta: &OpenapiMeta{
|
||||
Slurm: &MetaSlurm{
|
||||
Version: &MetaSlurmVersion{Major: Ptr("24"), Minor: Ptr("05"), Micro: Ptr("5")},
|
||||
Release: Ptr("24.05.5"),
|
||||
},
|
||||
},
|
||||
Errors: OpenapiErrors{},
|
||||
Warnings: OpenapiWarnings{},
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded OpenapiDiagResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if *decoded.Statistics.PartsPacked != *orig.Statistics.PartsPacked {
|
||||
t.Errorf("Statistics.PartsPacked: got %d, want %d", *decoded.Statistics.PartsPacked, *orig.Statistics.PartsPacked)
|
||||
}
|
||||
if *decoded.Meta.Slurm.Release != *orig.Meta.Slurm.Release {
|
||||
t.Errorf("Meta.Slurm.Release: got %s, want %s", *decoded.Meta.Slurm.Release, *orig.Meta.Slurm.Release)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenapiPingArrayRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiPingArrayResp{
|
||||
Pings: ControllerPingArray{
|
||||
{Hostname: Ptr("ctrl1"), Pinged: Ptr("UP"), Latency: Ptr(int64(10))},
|
||||
{Hostname: Ptr("ctrl2"), Pinged: Ptr("DOWN"), Latency: Ptr(int64(9999))},
|
||||
},
|
||||
Meta: &OpenapiMeta{
|
||||
Slurm: &MetaSlurm{
|
||||
Version: &MetaSlurmVersion{Major: Ptr("24"), Minor: Ptr("05"), Micro: Ptr("5")},
|
||||
},
|
||||
},
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded OpenapiPingArrayResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if len(decoded.Pings) != len(orig.Pings) {
|
||||
t.Fatalf("Pings length: got %d, want %d", len(decoded.Pings), len(orig.Pings))
|
||||
}
|
||||
if *decoded.Pings[0].Hostname != *orig.Pings[0].Hostname {
|
||||
t.Errorf("Pings[0].Hostname: got %s, want %s", *decoded.Pings[0].Hostname, *orig.Pings[0].Hostname)
|
||||
}
|
||||
if *decoded.Pings[1].Pinged != *orig.Pings[1].Pinged {
|
||||
t.Errorf("Pings[1].Pinged: got %s, want %s", *decoded.Pings[1].Pinged, *orig.Pings[1].Pinged)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenapiLicensesRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiLicensesResp{
|
||||
Licenses: Licenses{
|
||||
{LicenseName: Ptr("matlab"), Total: Ptr(int32(100)), Used: Ptr(int32(50))},
|
||||
{LicenseName: Ptr("ansys"), Total: Ptr(int32(10)), Used: Ptr(int32(3))},
|
||||
},
|
||||
LastUpdate: &Uint64NoVal{Set: Ptr(true), Number: Ptr(int64(1700000000))},
|
||||
Meta: &OpenapiMeta{
|
||||
Slurm: &MetaSlurm{
|
||||
Version: &MetaSlurmVersion{Major: Ptr("24"), Minor: Ptr("05"), Micro: Ptr("5")},
|
||||
},
|
||||
},
|
||||
}
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
var decoded OpenapiLicensesResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if len(decoded.Licenses) != len(orig.Licenses) {
|
||||
t.Fatalf("Licenses length: got %d, want %d", len(decoded.Licenses), len(orig.Licenses))
|
||||
}
|
||||
if *decoded.Licenses[0].LicenseName != *orig.Licenses[0].LicenseName {
|
||||
t.Errorf("Licenses[0].LicenseName: got %s, want %s", *decoded.Licenses[0].LicenseName, *orig.Licenses[0].LicenseName)
|
||||
}
|
||||
if *decoded.Licenses[1].Used != *orig.Licenses[1].Used {
|
||||
t.Errorf("Licenses[1].Used: got %d, want %d", *decoded.Licenses[1].Used, *orig.Licenses[1].Used)
|
||||
}
|
||||
if *decoded.LastUpdate.Number != *orig.LastUpdate.Number {
|
||||
t.Errorf("LastUpdate.Number: got %d, want %d", *decoded.LastUpdate.Number, *orig.LastUpdate.Number)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user