feat(slurmdb): add all slurmdb response types and supporting types
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
309
internal/slurm/types_slurmdb.go
Normal file
309
internal/slurm/types_slurmdb.go
Normal file
@@ -0,0 +1,309 @@
|
||||
package slurm
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SlurmDBD Response wrapper types — v0.0.40 OpenAPI SlurmDBD schemas
|
||||
// All fields are optional (pointer types) with json:"name,omitempty".
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// OpenapiSlurmdbdJobsResp is the response for listing SlurmDBD jobs.
|
||||
// Corresponds to v0.0.40_openapi_slurmdbd_jobs_resp.
|
||||
type OpenapiSlurmdbdJobsResp struct {
|
||||
Jobs JobList `json:"jobs,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiSlurmdbdConfigResp is the response for SlurmDBD configuration.
|
||||
// Corresponds to v0.0.40_openapi_slurmdbd_config_resp.
|
||||
type OpenapiSlurmdbdConfigResp struct {
|
||||
Clusters ClusterRecList `json:"clusters,omitempty"`
|
||||
Tres TresList `json:"tres,omitempty"`
|
||||
Accounts AccountList `json:"accounts,omitempty"`
|
||||
Users UserList `json:"users,omitempty"`
|
||||
Qos QosList `json:"qos,omitempty"`
|
||||
Wckeys WckeyList `json:"wckeys,omitempty"`
|
||||
Associations AssocList `json:"associations,omitempty"`
|
||||
Instances InstanceList `json:"instances,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiSlurmdbdQosResp is the response for listing QOS.
|
||||
// Corresponds to v0.0.40_openapi_slurmdbd_qos_resp.
|
||||
type OpenapiSlurmdbdQosResp struct {
|
||||
Qos QosList `json:"qos,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiSlurmdbdQosRemovedResp is the response for removed QOS.
|
||||
// Corresponds to v0.0.40_openapi_slurmdbd_qos_removed_resp.
|
||||
type OpenapiSlurmdbdQosRemovedResp struct {
|
||||
RemovedQos StringList `json:"removed_qos,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiSlurmdbdStatsResp is the response for SlurmDBD diagnostics.
|
||||
// Corresponds to v0.0.40_openapi_slurmdbd_stats_resp.
|
||||
type OpenapiSlurmdbdStatsResp struct {
|
||||
Statistics *StatsRec `json:"statistics,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiAssocsResp is the response for listing associations.
|
||||
// Corresponds to v0.0.40_openapi_assocs_resp.
|
||||
type OpenapiAssocsResp struct {
|
||||
Associations AssocList `json:"associations,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiAssocsRemovedResp is the response for removed associations.
|
||||
// Corresponds to v0.0.40_openapi_assocs_removed_resp.
|
||||
type OpenapiAssocsRemovedResp struct {
|
||||
RemovedAssociations StringList `json:"removed_associations,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiUsersResp is the response for listing users.
|
||||
// Corresponds to v0.0.40_openapi_users_resp.
|
||||
type OpenapiUsersResp struct {
|
||||
Users UserList `json:"users,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiClustersResp is the response for listing clusters.
|
||||
// Corresponds to v0.0.40_openapi_clusters_resp.
|
||||
type OpenapiClustersResp struct {
|
||||
Clusters ClusterRecList `json:"clusters,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiClustersRemovedResp is the response for deleted clusters.
|
||||
// Corresponds to v0.0.40_openapi_clusters_removed_resp.
|
||||
type OpenapiClustersRemovedResp struct {
|
||||
DeletedClusters StringList `json:"deleted_clusters,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiWckeyResp is the response for listing WCKeys.
|
||||
// Corresponds to v0.0.40_openapi_wckey_resp.
|
||||
type OpenapiWckeyResp struct {
|
||||
Wckeys WckeyList `json:"wckeys,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiWckeyRemovedResp is the response for deleted WCKeys.
|
||||
// Corresponds to v0.0.40_openapi_wckey_removed_resp.
|
||||
type OpenapiWckeyRemovedResp struct {
|
||||
DeletedWckeys StringList `json:"deleted_wckeys,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiAccountsResp is the response for listing accounts.
|
||||
// Corresponds to v0.0.40_openapi_accounts_resp.
|
||||
type OpenapiAccountsResp struct {
|
||||
Accounts AccountList `json:"accounts,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiAccountsRemovedResp is the response for removed accounts.
|
||||
// Corresponds to v0.0.40_openapi_accounts_removed_resp.
|
||||
type OpenapiAccountsRemovedResp struct {
|
||||
RemovedAccounts StringList `json:"removed_accounts,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiInstancesResp is the response for listing instances.
|
||||
// Corresponds to v0.0.40_openapi_instances_resp.
|
||||
type OpenapiInstancesResp struct {
|
||||
Instances InstanceList `json:"instances,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiTresResp is the response for listing TRES.
|
||||
// Corresponds to v0.0.40_openapi_tres_resp.
|
||||
// Note: JSON key for TRES is UPPERCASE per OpenAPI spec.
|
||||
type OpenapiTresResp struct {
|
||||
TRES TresList `json:"TRES,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiUsersAddCondResp is the response for adding users with conditions.
|
||||
// Corresponds to v0.0.40_openapi_users_add_cond_resp.
|
||||
type OpenapiUsersAddCondResp struct {
|
||||
AssociationCondition *UsersAddCond `json:"association_condition,omitempty"`
|
||||
User *UserShort `json:"user,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiUsersAddCondRespStr is the string response for adding users with conditions.
|
||||
// Corresponds to v0.0.40_openapi_users_add_cond_resp_str.
|
||||
type OpenapiUsersAddCondRespStr struct {
|
||||
AddedUsers *string `json:"added_users,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiAccountsAddCondResp is the response for adding accounts with conditions.
|
||||
// Corresponds to v0.0.40_openapi_accounts_add_cond_resp.
|
||||
type OpenapiAccountsAddCondResp struct {
|
||||
AssociationCondition *AccountsAddCond `json:"association_condition,omitempty"`
|
||||
Account *AccountShort `json:"account,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// OpenapiAccountsAddCondRespStr is the string response for adding accounts with conditions.
|
||||
// Corresponds to v0.0.40_openapi_accounts_add_cond_resp_str.
|
||||
type OpenapiAccountsAddCondRespStr struct {
|
||||
AddedAccounts *string `json:"added_accounts,omitempty"`
|
||||
Meta *OpenapiMeta `json:"meta,omitempty"`
|
||||
Errors OpenapiErrors `json:"errors,omitempty"`
|
||||
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Supporting types for SlurmDBD diagnostics
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// StatsRec represents SlurmDBD diagnostic statistics.
|
||||
// Corresponds to v0.0.40_stats_rec.
|
||||
type StatsRec struct {
|
||||
TimeStart *int64 `json:"time_start,omitempty"`
|
||||
Rollups RollupStatsList `json:"rollups,omitempty"`
|
||||
RPCs StatsRpcList `json:"RPCs,omitempty"`
|
||||
Users StatsUserList `json:"users,omitempty"`
|
||||
}
|
||||
|
||||
// RollupStatsList is a list of RollupStats.
|
||||
// Corresponds to v0.0.40_rollup_stats.
|
||||
type RollupStatsList []RollupStats
|
||||
|
||||
// RollupStats represents recorded rollup statistics.
|
||||
type RollupStats struct {
|
||||
Type *string `json:"type,omitempty"`
|
||||
LastRun *int32 `json:"last run,omitempty"`
|
||||
MaxCycle *int64 `json:"max_cycle,omitempty"`
|
||||
TotalTime *int64 `json:"total_time,omitempty"`
|
||||
TotalCycles *int64 `json:"total_cycles,omitempty"`
|
||||
MeanCycles *int64 `json:"mean_cycles,omitempty"`
|
||||
}
|
||||
|
||||
// StatsRpcList is a list of StatsRpc.
|
||||
// Corresponds to v0.0.40_stats_rpc_list.
|
||||
type StatsRpcList []StatsRpc
|
||||
|
||||
// StatsRpc represents RPC statistics.
|
||||
// Corresponds to v0.0.40_stats_rpc.
|
||||
type StatsRpc struct {
|
||||
RPC *string `json:"rpc,omitempty"`
|
||||
Count *int32 `json:"count,omitempty"`
|
||||
Time *StatsRpcTime `json:"time,omitempty"`
|
||||
}
|
||||
|
||||
// StatsRpcTime represents timing information for RPC statistics.
|
||||
type StatsRpcTime struct {
|
||||
Average *int64 `json:"average,omitempty"`
|
||||
Total *int64 `json:"total,omitempty"`
|
||||
}
|
||||
|
||||
// StatsUserList is a list of StatsUser.
|
||||
// Corresponds to v0.0.40_stats_user_list.
|
||||
type StatsUserList []StatsUser
|
||||
|
||||
// StatsUser represents per-user statistics.
|
||||
// Corresponds to v0.0.40_stats_user.
|
||||
type StatsUser struct {
|
||||
User *string `json:"user,omitempty"`
|
||||
Count *int32 `json:"count,omitempty"`
|
||||
Time *StatsUserTime `json:"time,omitempty"`
|
||||
}
|
||||
|
||||
// StatsUserTime represents timing information for user statistics.
|
||||
type StatsUserTime struct {
|
||||
Average *int64 `json:"average,omitempty"`
|
||||
Total *int64 `json:"total,omitempty"`
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// UsersAddCond and AccountsAddCond — association condition types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// UsersAddCond represents filters to select associations for users.
|
||||
// Corresponds to v0.0.40_users_add_cond.
|
||||
type UsersAddCond struct {
|
||||
Accounts StringList `json:"accounts,omitempty"`
|
||||
Association *AssocRecSet `json:"association,omitempty"`
|
||||
Clusters StringList `json:"clusters,omitempty"`
|
||||
Partitions StringList `json:"partitions,omitempty"`
|
||||
Users StringList `json:"users,omitempty"`
|
||||
Wckeys StringList `json:"wckeys,omitempty"`
|
||||
}
|
||||
|
||||
// AccountsAddCond represents filters for adding accounts.
|
||||
// Corresponds to v0.0.40_accounts_add_cond.
|
||||
type AccountsAddCond struct {
|
||||
Accounts StringList `json:"accounts,omitempty"`
|
||||
Association *AssocRecSet `json:"association,omitempty"`
|
||||
Clusters StringList `json:"clusters,omitempty"`
|
||||
}
|
||||
|
||||
// AssocRecSet represents association limits and options for user/account creation.
|
||||
// Corresponds to v0.0.40_assoc_rec_set.
|
||||
type AssocRecSet struct {
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
Defaultqos *string `json:"defaultqos,omitempty"`
|
||||
Grpjobs *Uint32NoVal `json:"grpjobs,omitempty"`
|
||||
Grpjobsaccrue *Uint32NoVal `json:"grpjobsaccrue,omitempty"`
|
||||
Grpsubmitjobs *Uint32NoVal `json:"grpsubmitjobs,omitempty"`
|
||||
Grptres TresList `json:"grptres,omitempty"`
|
||||
Grptresmins TresList `json:"grptresmins,omitempty"`
|
||||
Grptresrunmins TresList `json:"grptresrunmins,omitempty"`
|
||||
Grpwall *Uint32NoVal `json:"grpwall,omitempty"`
|
||||
Maxjobs *Uint32NoVal `json:"maxjobs,omitempty"`
|
||||
Maxjobsaccrue *Uint32NoVal `json:"maxjobsaccrue,omitempty"`
|
||||
Maxsubmitjobs *Uint32NoVal `json:"maxsubmitjobs,omitempty"`
|
||||
Maxtresminsperjob TresList `json:"maxtresminsperjob,omitempty"`
|
||||
Maxtresrunmins TresList `json:"maxtresrunmins,omitempty"`
|
||||
Maxtresperjob TresList `json:"maxtresperjob,omitempty"`
|
||||
Maxtrespernode TresList `json:"maxtrespernode,omitempty"`
|
||||
Maxwalldurationperjob *Uint32NoVal `json:"maxwalldurationperjob,omitempty"`
|
||||
Minpriothresh *Uint32NoVal `json:"minpriothresh,omitempty"`
|
||||
Parent *string `json:"parent,omitempty"`
|
||||
Priority *Uint32NoVal `json:"priority,omitempty"`
|
||||
Qoslevel QosStringIdList `json:"qoslevel,omitempty"`
|
||||
Fairshare *int32 `json:"fairshare,omitempty"`
|
||||
}
|
||||
816
internal/slurm/types_slurmdb_test.go
Normal file
816
internal/slurm/types_slurmdb_test.go
Normal file
@@ -0,0 +1,816 @@
|
||||
package slurm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSlurmdbJobsRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiSlurmdbdJobsResp{
|
||||
Jobs: JobList{
|
||||
{JobID: Ptr(int32(1)), Name: Ptr("test-job")},
|
||||
{JobID: Ptr(int32(2)), Name: Ptr("other-job")},
|
||||
},
|
||||
Meta: &OpenapiMeta{},
|
||||
Errors: OpenapiErrors{},
|
||||
Warnings: OpenapiWarnings{},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiSlurmdbdJobsResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Jobs) != 2 {
|
||||
t.Fatalf("expected 2 jobs, got %d", len(decoded.Jobs))
|
||||
}
|
||||
if *decoded.Jobs[0].JobID != 1 {
|
||||
t.Fatal("first job id mismatch")
|
||||
}
|
||||
if *decoded.Jobs[1].Name != "other-job" {
|
||||
t.Fatal("second job name mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbConfigRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiSlurmdbdConfigResp{
|
||||
Clusters: ClusterRecList{
|
||||
{Name: Ptr("cluster1")},
|
||||
},
|
||||
Tres: TresList{
|
||||
{Type: Ptr("cpu"), ID: Ptr(int32(1))},
|
||||
},
|
||||
Accounts: AccountList{
|
||||
{Name: Ptr("acct1")},
|
||||
},
|
||||
Users: UserList{
|
||||
{Name: Ptr("user1")},
|
||||
},
|
||||
Qos: QosList{
|
||||
{Name: Ptr("normal")},
|
||||
},
|
||||
Wckeys: WckeyList{
|
||||
{Name: Ptr("wckey1")},
|
||||
},
|
||||
Associations: AssocList{
|
||||
{Account: Ptr("acct1"), User: Ptr("user1")},
|
||||
},
|
||||
Instances: InstanceList{
|
||||
{InstanceID: Ptr("i-123")},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify lowercase "tres" key in JSON
|
||||
raw := string(data)
|
||||
if strings.Contains(raw, `"TRES"`) {
|
||||
t.Fatal("OpenapiSlurmdbdConfigResp should use lowercase 'tres', not uppercase 'TRES'")
|
||||
}
|
||||
if !strings.Contains(raw, `"tres"`) {
|
||||
t.Fatal("OpenapiSlurmdbdConfigResp should contain lowercase 'tres' key")
|
||||
}
|
||||
|
||||
var decoded OpenapiSlurmdbdConfigResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Clusters) != 1 || *decoded.Clusters[0].Name != "cluster1" {
|
||||
t.Fatal("clusters mismatch")
|
||||
}
|
||||
if len(decoded.Tres) != 1 || *decoded.Tres[0].Type != "cpu" {
|
||||
t.Fatal("tres mismatch")
|
||||
}
|
||||
if len(decoded.Accounts) != 1 || *decoded.Accounts[0].Name != "acct1" {
|
||||
t.Fatal("accounts mismatch")
|
||||
}
|
||||
if len(decoded.Users) != 1 || *decoded.Users[0].Name != "user1" {
|
||||
t.Fatal("users mismatch")
|
||||
}
|
||||
if len(decoded.Qos) != 1 || *decoded.Qos[0].Name != "normal" {
|
||||
t.Fatal("qos mismatch")
|
||||
}
|
||||
if len(decoded.Wckeys) != 1 || *decoded.Wckeys[0].Name != "wckey1" {
|
||||
t.Fatal("wckeys mismatch")
|
||||
}
|
||||
if len(decoded.Associations) != 1 || *decoded.Associations[0].Account != "acct1" {
|
||||
t.Fatal("associations mismatch")
|
||||
}
|
||||
if len(decoded.Instances) != 1 || *decoded.Instances[0].InstanceID != "i-123" {
|
||||
t.Fatal("instances mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbQosRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiSlurmdbdQosResp{
|
||||
Qos: QosList{
|
||||
{Name: Ptr("high"), ID: Ptr(int32(1))},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiSlurmdbdQosResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Qos) != 1 || *decoded.Qos[0].Name != "high" {
|
||||
t.Fatal("qos mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbQosRemovedRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiSlurmdbdQosRemovedResp{
|
||||
RemovedQos: StringList{"normal", "high"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiSlurmdbdQosRemovedResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.RemovedQos) != 2 || decoded.RemovedQos[0] != "normal" {
|
||||
t.Fatal("removed_qos mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbStatsRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiSlurmdbdStatsResp{
|
||||
Statistics: &StatsRec{
|
||||
TimeStart: Ptr(int64(1700000000)),
|
||||
Rollups: RollupStatsList{
|
||||
{Type: Ptr("internal"), MaxCycle: Ptr(int64(5))},
|
||||
},
|
||||
RPCs: StatsRpcList{
|
||||
{RPC: Ptr("SLURMCTLD_GET_JOB_INFO"), Count: Ptr(int32(100))},
|
||||
},
|
||||
Users: StatsUserList{
|
||||
{User: Ptr("root"), Count: Ptr(int32(50))},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiSlurmdbdStatsResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if decoded.Statistics == nil {
|
||||
t.Fatal("statistics is nil")
|
||||
}
|
||||
if *decoded.Statistics.TimeStart != 1700000000 {
|
||||
t.Fatal("time_start mismatch")
|
||||
}
|
||||
if len(decoded.Statistics.Rollups) != 1 || *decoded.Statistics.Rollups[0].Type != "internal" {
|
||||
t.Fatal("rollups mismatch")
|
||||
}
|
||||
if len(decoded.Statistics.RPCs) != 1 || *decoded.Statistics.RPCs[0].RPC != "SLURMCTLD_GET_JOB_INFO" {
|
||||
t.Fatal("RPCs mismatch")
|
||||
}
|
||||
if len(decoded.Statistics.Users) != 1 || *decoded.Statistics.Users[0].User != "root" {
|
||||
t.Fatal("users mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAssocsRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiAssocsResp{
|
||||
Associations: AssocList{
|
||||
{Account: Ptr("acct1"), User: Ptr("user1")},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiAssocsResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Associations) != 1 || *decoded.Associations[0].Account != "acct1" {
|
||||
t.Fatal("associations mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAssocsRemovedRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiAssocsRemovedResp{
|
||||
RemovedAssociations: StringList{"acct1_user1_cluster1"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiAssocsRemovedResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.RemovedAssociations) != 1 || decoded.RemovedAssociations[0] != "acct1_user1_cluster1" {
|
||||
t.Fatal("removed_associations mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbUsersRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiUsersResp{
|
||||
Users: UserList{
|
||||
{Name: Ptr("admin"), AdministratorLevel: []string{"Administrator"}},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiUsersResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Users) != 1 || *decoded.Users[0].Name != "admin" {
|
||||
t.Fatal("users mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbClustersRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiClustersResp{
|
||||
Clusters: ClusterRecList{
|
||||
{Name: Ptr("test-cluster"), Nodes: Ptr("node[1-10]")},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiClustersResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Clusters) != 1 || *decoded.Clusters[0].Name != "test-cluster" {
|
||||
t.Fatal("clusters mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbClustersRemovedRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiClustersRemovedResp{
|
||||
DeletedClusters: StringList{"old-cluster"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiClustersRemovedResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.DeletedClusters) != 1 || decoded.DeletedClusters[0] != "old-cluster" {
|
||||
t.Fatal("deleted_clusters mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbWckeyRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiWckeyResp{
|
||||
Wckeys: WckeyList{
|
||||
{Name: Ptr("wckey1"), Cluster: Ptr("cluster1")},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiWckeyResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Wckeys) != 1 || *decoded.Wckeys[0].Name != "wckey1" {
|
||||
t.Fatal("wckeys mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbWckeyRemovedRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiWckeyRemovedResp{
|
||||
DeletedWckeys: StringList{"old-wckey"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiWckeyRemovedResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.DeletedWckeys) != 1 || decoded.DeletedWckeys[0] != "old-wckey" {
|
||||
t.Fatal("deleted_wckeys mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAccountsRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiAccountsResp{
|
||||
Accounts: AccountList{
|
||||
{Name: Ptr("science"), Description: Ptr("Science dept"), Organization: Ptr("org1")},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiAccountsResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Accounts) != 1 || *decoded.Accounts[0].Name != "science" {
|
||||
t.Fatal("accounts mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAccountsRemovedRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiAccountsRemovedResp{
|
||||
RemovedAccounts: StringList{"old-acct"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiAccountsRemovedResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.RemovedAccounts) != 1 || decoded.RemovedAccounts[0] != "old-acct" {
|
||||
t.Fatal("removed_accounts mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbInstancesRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiInstancesResp{
|
||||
Instances: InstanceList{
|
||||
{InstanceID: Ptr("i-abc123"), Cluster: Ptr("cluster1")},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiInstancesResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Instances) != 1 || *decoded.Instances[0].InstanceID != "i-abc123" {
|
||||
t.Fatal("instances mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbTresRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiTresResp{
|
||||
TRES: TresList{
|
||||
{Type: Ptr("cpu"), ID: Ptr(int32(1)), Count: Ptr(int64(100))},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify UPPERCASE "TRES" key in JSON
|
||||
raw := string(data)
|
||||
if !strings.Contains(raw, `"TRES"`) {
|
||||
t.Fatalf("OpenapiTresResp should use UPPERCASE 'TRES' key, got: %s", raw)
|
||||
}
|
||||
if strings.Contains(raw, `"tres"`) {
|
||||
t.Fatal("OpenapiTresResp should NOT contain lowercase 'tres'")
|
||||
}
|
||||
|
||||
var decoded OpenapiTresResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.TRES) != 1 || *decoded.TRES[0].Type != "cpu" {
|
||||
t.Fatal("TRES mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbTresRespUppercaseKey(t *testing.T) {
|
||||
raw := `{"TRES": [{"type": "mem", "id": 2, "count": 1000}]}`
|
||||
var decoded OpenapiTresResp
|
||||
if err := json.Unmarshal([]byte(raw), &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(decoded.TRES) != 1 || *decoded.TRES[0].Type != "mem" {
|
||||
t.Fatal("TRES uppercase key parse failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbConfigRespLowercaseTresKey(t *testing.T) {
|
||||
raw := `{"tres": [{"type": "cpu", "id": 1, "count": 100}]}`
|
||||
var decoded OpenapiSlurmdbdConfigResp
|
||||
if err := json.Unmarshal([]byte(raw), &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(decoded.Tres) != 1 || *decoded.Tres[0].Type != "cpu" {
|
||||
t.Fatal("config resp lowercase tres key parse failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbUsersAddCondRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiUsersAddCondResp{
|
||||
AssociationCondition: &UsersAddCond{
|
||||
Accounts: StringList{"acct1", "acct2"},
|
||||
Clusters: StringList{"cluster1"},
|
||||
Users: StringList{"user1", "user2"},
|
||||
Wckeys: StringList{"wckey1"},
|
||||
Partitions: StringList{"partition1"},
|
||||
},
|
||||
User: &UserShort{
|
||||
Adminlevel: []string{"Administrator"},
|
||||
Defaultaccount: Ptr("acct1"),
|
||||
Defaultwckey: Ptr("wckey1"),
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiUsersAddCondResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if decoded.AssociationCondition == nil {
|
||||
t.Fatal("association_condition is nil")
|
||||
}
|
||||
if len(decoded.AssociationCondition.Accounts) != 2 {
|
||||
t.Fatal("accounts count mismatch")
|
||||
}
|
||||
if decoded.User == nil || *decoded.User.Defaultaccount != "acct1" {
|
||||
t.Fatal("user mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbUsersAddCondRespStrRoundTrip(t *testing.T) {
|
||||
orig := OpenapiUsersAddCondRespStr{
|
||||
AddedUsers: Ptr("user1,user2,user3"),
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiUsersAddCondRespStr
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if decoded.AddedUsers == nil || *decoded.AddedUsers != "user1,user2,user3" {
|
||||
t.Fatal("added_users mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAccountsAddCondRespRoundTrip(t *testing.T) {
|
||||
orig := OpenapiAccountsAddCondResp{
|
||||
AssociationCondition: &AccountsAddCond{
|
||||
Accounts: StringList{"acct1"},
|
||||
Clusters: StringList{"cluster1"},
|
||||
},
|
||||
Account: &AccountShort{
|
||||
Description: Ptr("Science department"),
|
||||
Organization: Ptr("university"),
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiAccountsAddCondResp
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if decoded.AssociationCondition == nil || len(decoded.AssociationCondition.Accounts) != 1 {
|
||||
t.Fatal("association_condition mismatch")
|
||||
}
|
||||
if decoded.Account == nil || *decoded.Account.Description != "Science department" {
|
||||
t.Fatal("account mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAccountsAddCondRespStrRoundTrip(t *testing.T) {
|
||||
orig := OpenapiAccountsAddCondRespStr{
|
||||
AddedAccounts: Ptr("acct1,acct2"),
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded OpenapiAccountsAddCondRespStr
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if decoded.AddedAccounts == nil || *decoded.AddedAccounts != "acct1,acct2" {
|
||||
t.Fatal("added_accounts mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbStatsRecRoundTrip(t *testing.T) {
|
||||
orig := StatsRec{
|
||||
TimeStart: Ptr(int64(1700000000)),
|
||||
Rollups: RollupStatsList{
|
||||
{
|
||||
Type: Ptr("internal"),
|
||||
LastRun: Ptr(int32(1700001000)),
|
||||
MaxCycle: Ptr(int64(10)),
|
||||
TotalTime: Ptr(int64(100)),
|
||||
TotalCycles: Ptr(int64(50)),
|
||||
MeanCycles: Ptr(int64(2)),
|
||||
},
|
||||
},
|
||||
RPCs: StatsRpcList{
|
||||
{
|
||||
RPC: Ptr("GET_JOBS"),
|
||||
Count: Ptr(int32(500)),
|
||||
Time: &StatsRpcTime{
|
||||
Average: Ptr(int64(100)),
|
||||
Total: Ptr(int64(50000)),
|
||||
},
|
||||
},
|
||||
},
|
||||
Users: StatsUserList{
|
||||
{
|
||||
User: Ptr("admin"),
|
||||
Count: Ptr(int32(200)),
|
||||
Time: &StatsUserTime{
|
||||
Average: Ptr(int64(50)),
|
||||
Total: Ptr(int64(10000)),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded StatsRec
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if *decoded.TimeStart != 1700000000 {
|
||||
t.Fatal("time_start mismatch")
|
||||
}
|
||||
if len(decoded.Rollups) != 1 || *decoded.Rollups[0].Type != "internal" {
|
||||
t.Fatal("rollups mismatch")
|
||||
}
|
||||
if *decoded.Rollups[0].MaxCycle != 10 {
|
||||
t.Fatal("max_cycle mismatch")
|
||||
}
|
||||
if len(decoded.RPCs) != 1 || *decoded.RPCs[0].RPC != "GET_JOBS" {
|
||||
t.Fatal("RPCs mismatch")
|
||||
}
|
||||
if decoded.RPCs[0].Time == nil || *decoded.RPCs[0].Time.Average != 100 {
|
||||
t.Fatal("RPC time.average mismatch")
|
||||
}
|
||||
if len(decoded.Users) != 1 || *decoded.Users[0].User != "admin" {
|
||||
t.Fatal("users mismatch")
|
||||
}
|
||||
if decoded.Users[0].Time == nil || *decoded.Users[0].Time.Total != 10000 {
|
||||
t.Fatal("user time.total mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbStatsRecRPCsUppercaseKey(t *testing.T) {
|
||||
raw := `{"time_start": 1700000000, "RPCs": [{"rpc": "TEST", "count": 1}]}`
|
||||
var decoded StatsRec
|
||||
if err := json.Unmarshal([]byte(raw), &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(decoded.RPCs) != 1 || *decoded.RPCs[0].RPC != "TEST" {
|
||||
t.Fatal("RPCs uppercase key parse failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbRollupStatsRoundTrip(t *testing.T) {
|
||||
orig := RollupStats{
|
||||
Type: Ptr("user"),
|
||||
LastRun: Ptr(int32(1700002000)),
|
||||
MaxCycle: Ptr(int64(20)),
|
||||
TotalTime: Ptr(int64(200)),
|
||||
TotalCycles: Ptr(int64(100)),
|
||||
MeanCycles: Ptr(int64(2)),
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded RollupStats
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if *decoded.Type != "user" {
|
||||
t.Fatal("type mismatch")
|
||||
}
|
||||
if *decoded.LastRun != 1700002000 {
|
||||
t.Fatal("last run mismatch")
|
||||
}
|
||||
if *decoded.TotalCycles != 100 {
|
||||
t.Fatal("total_cycles mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAssocRecSetRoundTrip(t *testing.T) {
|
||||
orig := AssocRecSet{
|
||||
Comment: Ptr("test comment"),
|
||||
Defaultqos: Ptr("normal"),
|
||||
Fairshare: Ptr(int32(100)),
|
||||
Parent: Ptr("parent-acct"),
|
||||
Grptres: TresList{{Type: Ptr("cpu"), Count: Ptr(int64(1000))}},
|
||||
Maxtresperjob: TresList{{Type: Ptr("mem"), Count: Ptr(int64(4096))}},
|
||||
Qoslevel: QosStringIdList{"high", "normal"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded AssocRecSet
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if *decoded.Comment != "test comment" {
|
||||
t.Fatal("comment mismatch")
|
||||
}
|
||||
if *decoded.Defaultqos != "normal" {
|
||||
t.Fatal("defaultqos mismatch")
|
||||
}
|
||||
if *decoded.Fairshare != 100 {
|
||||
t.Fatal("fairshare mismatch")
|
||||
}
|
||||
if len(decoded.Grptres) != 1 || *decoded.Grptres[0].Type != "cpu" {
|
||||
t.Fatal("grptres mismatch")
|
||||
}
|
||||
if len(decoded.Qoslevel) != 2 || decoded.Qoslevel[0] != "high" {
|
||||
t.Fatal("qoslevel mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbUsersAddCondRoundTrip(t *testing.T) {
|
||||
orig := UsersAddCond{
|
||||
Accounts: StringList{"acct1"},
|
||||
Clusters: StringList{"cluster1"},
|
||||
Partitions: StringList{"part1"},
|
||||
Users: StringList{"user1", "user2"},
|
||||
Wckeys: StringList{"wckey1"},
|
||||
Association: &AssocRecSet{
|
||||
Comment: Ptr("assoc comment"),
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded UsersAddCond
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Users) != 2 {
|
||||
t.Fatal("users count mismatch")
|
||||
}
|
||||
if decoded.Association == nil || *decoded.Association.Comment != "assoc comment" {
|
||||
t.Fatal("association mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbAccountsAddCondRoundTrip(t *testing.T) {
|
||||
orig := AccountsAddCond{
|
||||
Accounts: StringList{"acct1", "acct2"},
|
||||
Clusters: StringList{"cluster1"},
|
||||
Association: &AssocRecSet{
|
||||
Fairshare: Ptr(int32(50)),
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var decoded AccountsAddCond
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decoded.Accounts) != 2 {
|
||||
t.Fatal("accounts count mismatch")
|
||||
}
|
||||
if decoded.Association == nil || *decoded.Association.Fairshare != 50 {
|
||||
t.Fatal("association mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlurmdbEmptyResponses(t *testing.T) {
|
||||
types := []interface{}{
|
||||
OpenapiSlurmdbdJobsResp{},
|
||||
OpenapiSlurmdbdConfigResp{},
|
||||
OpenapiSlurmdbdQosResp{},
|
||||
OpenapiSlurmdbdQosRemovedResp{},
|
||||
OpenapiSlurmdbdStatsResp{},
|
||||
OpenapiAssocsResp{},
|
||||
OpenapiAssocsRemovedResp{},
|
||||
OpenapiUsersResp{},
|
||||
OpenapiClustersResp{},
|
||||
OpenapiClustersRemovedResp{},
|
||||
OpenapiWckeyResp{},
|
||||
OpenapiWckeyRemovedResp{},
|
||||
OpenapiAccountsResp{},
|
||||
OpenapiAccountsRemovedResp{},
|
||||
OpenapiInstancesResp{},
|
||||
OpenapiTresResp{},
|
||||
OpenapiUsersAddCondResp{},
|
||||
OpenapiUsersAddCondRespStr{},
|
||||
OpenapiAccountsAddCondResp{},
|
||||
OpenapiAccountsAddCondRespStr{},
|
||||
StatsRec{},
|
||||
RollupStats{},
|
||||
StatsRpc{},
|
||||
StatsUser{},
|
||||
UsersAddCond{},
|
||||
AccountsAddCond{},
|
||||
AssocRecSet{},
|
||||
}
|
||||
|
||||
for i, v := range types {
|
||||
data, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Fatalf("type %d: marshal error: %v", i, err)
|
||||
}
|
||||
if string(data) != "{}" {
|
||||
t.Fatalf("type %d: empty struct should marshal to {}, got %s", i, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user