feat: runtime manager

This commit is contained in:
Ilia Denisov
2026-04-28 20:39:18 +02:00
committed by GitHub
parent e0a99b346b
commit a7cee15115
289 changed files with 45660 additions and 2207 deletions
@@ -0,0 +1,115 @@
package handlers
import (
"encoding/json"
"errors"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Tests for the read-only handlers (`internalListRuntimes`,
// `internalGetRuntime`). These bypass the service layer and read
// directly from `ports.RuntimeRecordStore` — see
// `rtmanager/docs/services.md` §18.
func TestListHandlerReturnsEmptyItemsForEmptyStore(t *testing.T) {
t.Parallel()
deps := Dependencies{RuntimeRecords: newFakeRuntimeRecords()}
rec := drive(t, deps, http.MethodGet, "/api/v1/internal/runtimes", nil, nil)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, JSONContentType, rec.Header().Get("Content-Type"))
var resp runtimesListResponse
require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp))
require.NotNil(t, resp.Items, "items must never be nil")
assert.Empty(t, resp.Items)
}
func TestListHandlerReturnsEveryStoredRecord(t *testing.T) {
t.Parallel()
store := newFakeRuntimeRecords()
store.put(sampleRunningRecord(t))
store.put(sampleStoppedRecord(t))
rec := drive(t, Dependencies{RuntimeRecords: store}, http.MethodGet, "/api/v1/internal/runtimes", nil, nil)
require.Equal(t, http.StatusOK, rec.Code)
var resp runtimesListResponse
require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp))
require.Len(t, resp.Items, 2)
gotIDs := map[string]string{}
for _, item := range resp.Items {
gotIDs[item.GameID] = item.Status
}
assert.Equal(t, "running", gotIDs["game-test"])
assert.Equal(t, "stopped", gotIDs["game-stopped"])
}
func TestListHandlerReturnsInternalErrorWhenStoreFails(t *testing.T) {
t.Parallel()
store := newFakeRuntimeRecords()
store.listErr = errors.New("postgres exploded")
rec := drive(t, Dependencies{RuntimeRecords: store}, http.MethodGet, "/api/v1/internal/runtimes", nil, nil)
body := decodeErrorBody(t, rec, http.StatusInternalServerError)
assert.Equal(t, "internal_error", body.Code)
}
func TestListHandlerReturnsInternalErrorWhenStoreNotWired(t *testing.T) {
t.Parallel()
rec := drive(t, Dependencies{}, http.MethodGet, "/api/v1/internal/runtimes", nil, nil)
body := decodeErrorBody(t, rec, http.StatusInternalServerError)
assert.Equal(t, "internal_error", body.Code)
}
func TestGetHandlerReturnsTheRecord(t *testing.T) {
t.Parallel()
store := newFakeRuntimeRecords()
record := sampleRunningRecord(t)
store.put(record)
rec := drive(t, Dependencies{RuntimeRecords: store}, http.MethodGet, "/api/v1/internal/runtimes/game-test", nil, nil)
resp := decodeRecordResponse(t, rec)
assert.Equal(t, "game-test", resp.GameID)
assert.Equal(t, "running", resp.Status)
if assert.NotNil(t, resp.CurrentImageRef) {
assert.Equal(t, "galaxy/game:v1.2.3", *resp.CurrentImageRef)
}
}
func TestGetHandlerReturnsNotFoundForMissingRecord(t *testing.T) {
t.Parallel()
rec := drive(t, Dependencies{RuntimeRecords: newFakeRuntimeRecords()}, http.MethodGet, "/api/v1/internal/runtimes/game-missing", nil, nil)
body := decodeErrorBody(t, rec, http.StatusNotFound)
assert.Equal(t, "not_found", body.Code)
}
func TestGetHandlerReturnsInternalErrorWhenStoreFails(t *testing.T) {
t.Parallel()
store := newFakeRuntimeRecords()
store.getErr = errors.New("transport blew up")
rec := drive(t, Dependencies{RuntimeRecords: store}, http.MethodGet, "/api/v1/internal/runtimes/game-test", nil, nil)
body := decodeErrorBody(t, rec, http.StatusInternalServerError)
assert.Equal(t, "internal_error", body.Code)
}
func TestGetHandlerReturnsInternalErrorWhenStoreNotWired(t *testing.T) {
t.Parallel()
rec := drive(t, Dependencies{}, http.MethodGet, "/api/v1/internal/runtimes/game-test", nil, nil)
body := decodeErrorBody(t, rec, http.StatusInternalServerError)
assert.Equal(t, "internal_error", body.Code)
}