Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions internal/api/cmkapi/enum_db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package cmkapi

import (
"database/sql/driver"
"errors"
"fmt"
"slices"
)

var (
// ErrInvalidKeyState is returned when a key state value is not recognized.
ErrInvalidKeyState = errors.New("invalid key state")
// ErrInvalidSystemStatus is returned when a system status value is not recognized.
ErrInvalidSystemStatus = errors.New("invalid system status")
// ErrUnexpectedScanType is returned when Scan receives a value that is not string or []byte.
ErrUnexpectedScanType = errors.New("unexpected scan type")
)

// Valid KeyState values.
var validKeyStates = []KeyState{
KeyStateDELETED, KeyStateDETACHED, KeyStateDETACHING, KeyStateDISABLED,
KeyStateENABLED, KeyStateFORBIDDEN, KeyStatePENDINGDELETION,
KeyStatePENDINGIMPORT, KeyStateUNKNOWN,
}

// Valid SystemStatus values.
var validSystemStatuses = []SystemStatus{
SystemStatusCONNECTED, SystemStatusDISCONNECTED,
SystemStatusFAILED, SystemStatusPROCESSING,
}

// Valid returns true if the KeyState is a known value.
func (s KeyState) Valid() bool {
return slices.Contains(validKeyStates, s)
}

// Value implements the driver.Valuer interface.
func (s KeyState) Value() (driver.Value, error) {
if s == "" {
return "", nil
}
if !s.Valid() {
return nil, fmt.Errorf("%w: %q", ErrInvalidKeyState, s)
}
return string(s), nil
}

// Scan implements the sql.Scanner interface.
func (s *KeyState) Scan(value any) error {
if value == nil {
*s = ""
return nil
}
var sv string
switch v := value.(type) {
case string:
sv = v
case []byte:
sv = string(v)
default:
return fmt.Errorf("%w: expected string or []byte, got %T", ErrUnexpectedScanType, value)
}
*s = KeyState(sv)
if !s.Valid() {
return fmt.Errorf("%w: %q", ErrInvalidKeyState, sv)
}
return nil
}

// Valid returns true if the SystemStatus is a known value.
func (s SystemStatus) Valid() bool {
return slices.Contains(validSystemStatuses, s)
}

// Value implements the driver.Valuer interface.
func (s SystemStatus) Value() (driver.Value, error) {
if s == "" {
return "", nil
}
if !s.Valid() {
return nil, fmt.Errorf("%w: %q", ErrInvalidSystemStatus, s)
}
return string(s), nil
}

// Scan implements the sql.Scanner interface.
func (s *SystemStatus) Scan(value any) error {
if value == nil {
*s = ""
return nil
}
var sv string
switch v := value.(type) {
case string:
sv = v
case []byte:
sv = string(v)
default:
return fmt.Errorf("%w: expected string or []byte, got %T", ErrUnexpectedScanType, value)
}
*s = SystemStatus(sv)
if !s.Valid() {
return fmt.Errorf("%w: %q", ErrInvalidSystemStatus, sv)
}
return nil
}
176 changes: 176 additions & 0 deletions internal/api/cmkapi/enum_db_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package cmkapi_test

import (
"errors"
"testing"

"github.com/openkcm/cmk/internal/api/cmkapi"
)

// --- KeyState tests ---

func TestKeyState_Valid(t *testing.T) {
if !cmkapi.KeyStateENABLED.Valid() {
t.Fatal("expected ENABLED to be valid")
}
if cmkapi.KeyState("BOGUS").Valid() {
t.Fatal("expected BOGUS to be invalid")
}
}

func TestKeyState_Value_Valid(t *testing.T) {
v, err := cmkapi.KeyStateENABLED.Value()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v != "ENABLED" {
t.Fatalf("expected ENABLED, got %v", v)
}
}

func TestKeyState_Value_Empty(t *testing.T) {
v, err := cmkapi.KeyState("").Value()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v != "" {
t.Fatalf("expected empty, got %v", v)
}
}

func TestKeyState_Value_Invalid(t *testing.T) {
_, err := cmkapi.KeyState("BOGUS").Value()
if !errors.Is(err, cmkapi.ErrInvalidKeyState) {
t.Fatalf("expected ErrInvalidKeyState, got %v", err)
}
}

func TestKeyState_Scan_String(t *testing.T) {
var s cmkapi.KeyState
if err := s.Scan("ENABLED"); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != cmkapi.KeyStateENABLED {
t.Fatalf("expected ENABLED, got %s", s)
}
}

func TestKeyState_Scan_Bytes(t *testing.T) {
var s cmkapi.KeyState
if err := s.Scan([]byte("DISABLED")); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != cmkapi.KeyStateDISABLED {
t.Fatalf("expected DISABLED, got %s", s)
}
}

func TestKeyState_Scan_Nil(t *testing.T) {
var s cmkapi.KeyState
if err := s.Scan(nil); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "" {
t.Fatalf("expected empty, got %s", s)
}
}

func TestKeyState_Scan_Invalid(t *testing.T) {
var s cmkapi.KeyState
err := s.Scan("BOGUS")
if !errors.Is(err, cmkapi.ErrInvalidKeyState) {
t.Fatalf("expected ErrInvalidKeyState, got %v", err)
}
}

func TestKeyState_Scan_WrongType(t *testing.T) {
var s cmkapi.KeyState
err := s.Scan(123)
if !errors.Is(err, cmkapi.ErrUnexpectedScanType) {
t.Fatalf("expected ErrUnexpectedScanType, got %v", err)
}
}

// --- SystemStatus tests ---

func TestSystemStatus_Valid(t *testing.T) {
if !cmkapi.SystemStatusCONNECTED.Valid() {
t.Fatal("expected CONNECTED to be valid")
}
if cmkapi.SystemStatus("BOGUS").Valid() {
t.Fatal("expected BOGUS to be invalid")
}
}

func TestSystemStatus_Value_Valid(t *testing.T) {
v, err := cmkapi.SystemStatusCONNECTED.Value()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v != "CONNECTED" {
t.Fatalf("expected CONNECTED, got %v", v)
}
}

func TestSystemStatus_Value_Empty(t *testing.T) {
v, err := cmkapi.SystemStatus("").Value()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v != "" {
t.Fatalf("expected empty, got %v", v)
}
}

func TestSystemStatus_Value_Invalid(t *testing.T) {
_, err := cmkapi.SystemStatus("BOGUS").Value()
if !errors.Is(err, cmkapi.ErrInvalidSystemStatus) {
t.Fatalf("expected ErrInvalidSystemStatus, got %v", err)
}
}

func TestSystemStatus_Scan_String(t *testing.T) {
var s cmkapi.SystemStatus
if err := s.Scan("CONNECTED"); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != cmkapi.SystemStatusCONNECTED {
t.Fatalf("expected CONNECTED, got %s", s)
}
}

func TestSystemStatus_Scan_Bytes(t *testing.T) {
var s cmkapi.SystemStatus
if err := s.Scan([]byte("FAILED")); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != cmkapi.SystemStatusFAILED {
t.Fatalf("expected FAILED, got %s", s)
}
}

func TestSystemStatus_Scan_Nil(t *testing.T) {
var s cmkapi.SystemStatus
if err := s.Scan(nil); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "" {
t.Fatalf("expected empty, got %s", s)
}
}

func TestSystemStatus_Scan_Invalid(t *testing.T) {
var s cmkapi.SystemStatus
err := s.Scan("BOGUS")
if !errors.Is(err, cmkapi.ErrInvalidSystemStatus) {
t.Fatalf("expected ErrInvalidSystemStatus, got %v", err)
}
}

func TestSystemStatus_Scan_WrongType(t *testing.T) {
var s cmkapi.SystemStatus
err := s.Scan(99)
if !errors.Is(err, cmkapi.ErrUnexpectedScanType) {
t.Fatalf("expected ErrUnexpectedScanType, got %v", err)
}
}
Loading
Loading