- pkg/api/provider.go: remove banned os/syscall imports; delegate to
new process.KillPID and process.IsPIDAlive exported helpers
- service.go: rename `sr` → `startResult`; add KillPID/IsPIDAlive exports
- runner.go: rename `aggResult` → `aggregate` in all three RunXxx methods;
add usage-example comments on all exported functions
- process.go: replace prose doc-comments with usage-example comments
- buffer.go, registry.go, health.go: replace prose comments with examples
- buffer_test.go: rename TestRingBuffer_Basics_Good → TestBuffer_{Write,String,Reset}_{Good,Bad,Ugly}
- All test files: add missing _Bad and _Ugly variants for all functions
(daemon, health, pidfile, registry, runner, process, program, exec, pkg/api)
Co-Authored-By: Virgil <virgil@lethean.io>
185 lines
4.9 KiB
Go
185 lines
4.9 KiB
Go
// SPDX-Licence-Identifier: EUPL-1.2
|
|
|
|
package api_test
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
process "dappco.re/go/core/process"
|
|
processapi "dappco.re/go/core/process/pkg/api"
|
|
goapi "forge.lthn.ai/core/api"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func init() {
|
|
gin.SetMode(gin.TestMode)
|
|
}
|
|
|
|
func TestProcessProvider_Name_Good(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
assert.Equal(t, "process", p.Name())
|
|
}
|
|
|
|
func TestProcessProvider_BasePath_Good(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
assert.Equal(t, "/api/process", p.BasePath())
|
|
}
|
|
|
|
func TestProcessProvider_Channels_Good(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
channels := p.Channels()
|
|
assert.Contains(t, channels, "process.daemon.started")
|
|
assert.Contains(t, channels, "process.daemon.stopped")
|
|
assert.Contains(t, channels, "process.daemon.health")
|
|
}
|
|
|
|
func TestProcessProvider_Describe_Good(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
descs := p.Describe()
|
|
assert.GreaterOrEqual(t, len(descs), 4)
|
|
|
|
// Verify all descriptions have required fields
|
|
for _, d := range descs {
|
|
assert.NotEmpty(t, d.Method)
|
|
assert.NotEmpty(t, d.Path)
|
|
assert.NotEmpty(t, d.Summary)
|
|
assert.NotEmpty(t, d.Tags)
|
|
}
|
|
}
|
|
|
|
func TestProcessProvider_ListDaemons_Good(t *testing.T) {
|
|
// Use a temp directory so the registry has no daemons
|
|
dir := t.TempDir()
|
|
registry := newTestRegistry(dir)
|
|
p := processapi.NewProvider(registry, nil)
|
|
|
|
r := setupRouter(p)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/process/daemons", nil)
|
|
r.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
body := w.Body.String()
|
|
assert.NotEmpty(t, body)
|
|
}
|
|
|
|
func TestProcessProvider_GetDaemon_Bad(t *testing.T) {
|
|
dir := t.TempDir()
|
|
registry := newTestRegistry(dir)
|
|
p := processapi.NewProvider(registry, nil)
|
|
|
|
r := setupRouter(p)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/process/daemons/test/nonexistent", nil)
|
|
r.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
|
}
|
|
|
|
func TestProcessProvider_RegistersAsRouteGroup_Good(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
|
|
engine, err := goapi.New()
|
|
require.NoError(t, err)
|
|
|
|
engine.Register(p)
|
|
assert.Len(t, engine.Groups(), 1)
|
|
assert.Equal(t, "process", engine.Groups()[0].Name())
|
|
}
|
|
|
|
func TestProcessProvider_StreamGroup_Good(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
|
|
engine, err := goapi.New()
|
|
require.NoError(t, err)
|
|
|
|
engine.Register(p)
|
|
|
|
// Engine.Channels() discovers StreamGroups
|
|
channels := engine.Channels()
|
|
assert.Contains(t, channels, "process.daemon.started")
|
|
}
|
|
|
|
func TestProcessProvider_ListDaemons_Bad(t *testing.T) {
|
|
t.Run("get non-existent daemon returns 404", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
registry := newTestRegistry(dir)
|
|
p := processapi.NewProvider(registry, nil)
|
|
|
|
r := setupRouter(p)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/process/daemons/nope/missing", nil)
|
|
r.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
|
})
|
|
}
|
|
|
|
func TestProcessProvider_ListDaemons_Ugly(t *testing.T) {
|
|
t.Run("nil registry falls back to default", func(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
r := setupRouter(p)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/process/daemons", nil)
|
|
r.ServeHTTP(w, req)
|
|
|
|
// Should succeed — default registry returns empty list
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
})
|
|
}
|
|
|
|
func TestProcessProvider_Element_Good(t *testing.T) {
|
|
p := processapi.NewProvider(nil, nil)
|
|
element := p.Element()
|
|
assert.Equal(t, "core-process-panel", element.Tag)
|
|
assert.NotEmpty(t, element.Source)
|
|
}
|
|
|
|
func TestProcessProvider_Element_Bad(t *testing.T) {
|
|
t.Run("stop non-existent daemon returns 404", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
registry := newTestRegistry(dir)
|
|
p := processapi.NewProvider(registry, nil)
|
|
|
|
r := setupRouter(p)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("POST", "/api/process/daemons/nope/missing/stop", nil)
|
|
r.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
|
})
|
|
}
|
|
|
|
func TestProcessProvider_Element_Ugly(t *testing.T) {
|
|
t.Run("health check on non-existent daemon returns 404", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
registry := newTestRegistry(dir)
|
|
p := processapi.NewProvider(registry, nil)
|
|
|
|
r := setupRouter(p)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/process/daemons/nope/missing/health", nil)
|
|
r.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
|
})
|
|
}
|
|
|
|
// -- Test helpers -------------------------------------------------------------
|
|
|
|
func setupRouter(p *processapi.ProcessProvider) *gin.Engine {
|
|
r := gin.New()
|
|
rg := r.Group(p.BasePath())
|
|
p.RegisterRoutes(rg)
|
|
return r
|
|
}
|
|
|
|
// newTestRegistry creates a process.Registry backed by a test directory.
|
|
func newTestRegistry(dir string) *process.Registry {
|
|
return process.NewRegistry(dir)
|
|
}
|