2026-03-27 17:55:06 +00:00
|
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2026-03-30 00:00:33 +00:00
|
|
|
"bytes"
|
2026-03-30 20:12:39 +00:00
|
|
|
"io"
|
2026-03-30 00:00:33 +00:00
|
|
|
"os"
|
2026-03-27 17:55:06 +00:00
|
|
|
"testing"
|
|
|
|
|
|
2026-03-30 16:40:53 +00:00
|
|
|
agentpkg "dappco.re/go/agent"
|
2026-03-30 20:12:39 +00:00
|
|
|
"dappco.re/go/agent/pkg/agentic"
|
2026-03-27 17:55:06 +00:00
|
|
|
"dappco.re/go/core"
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
)
|
|
|
|
|
|
2026-03-30 21:30:49 +00:00
|
|
|
// newTestCore creates a minimal Core with application commands registered.
|
2026-03-27 17:55:06 +00:00
|
|
|
func newTestCore(t *testing.T) *core.Core {
|
|
|
|
|
t.Helper()
|
2026-03-30 21:30:49 +00:00
|
|
|
c := core.New(core.WithOption("name", "core-agent"))
|
2026-03-27 17:55:06 +00:00
|
|
|
c.App().Version = "test"
|
2026-03-30 21:30:49 +00:00
|
|
|
registerApplicationCommands(c)
|
2026-03-30 00:00:33 +00:00
|
|
|
c.Cli().SetOutput(&bytes.Buffer{})
|
2026-03-27 17:55:06 +00:00
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 00:00:33 +00:00
|
|
|
func withArgs(t *testing.T, args ...string) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
previous := os.Args
|
|
|
|
|
os.Args = append([]string(nil), args...)
|
|
|
|
|
t.Cleanup(func() {
|
|
|
|
|
os.Args = previous
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 20:12:39 +00:00
|
|
|
func captureStdout(t *testing.T, run func()) string {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
old := os.Stdout
|
|
|
|
|
reader, writer, err := os.Pipe()
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("pipe stdout: %v", err)
|
|
|
|
|
}
|
|
|
|
|
os.Stdout = writer
|
|
|
|
|
defer func() {
|
|
|
|
|
os.Stdout = old
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
run()
|
|
|
|
|
|
|
|
|
|
if err := writer.Close(); err != nil {
|
|
|
|
|
t.Fatalf("close writer: %v", err)
|
|
|
|
|
}
|
|
|
|
|
data, err := io.ReadAll(reader)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("read stdout: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if err := reader.Close(); err != nil {
|
|
|
|
|
t.Fatalf("close reader: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string(data)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 00:00:33 +00:00
|
|
|
func TestCommands_ApplyLogLevel_Good(t *testing.T) {
|
|
|
|
|
defer core.SetLevel(core.LevelInfo)
|
|
|
|
|
|
|
|
|
|
args := applyLogLevel([]string{"--quiet", "version"})
|
|
|
|
|
assert.Equal(t, []string{"version"}, args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_ApplyLogLevel_Bad(t *testing.T) {
|
|
|
|
|
defer core.SetLevel(core.LevelInfo)
|
|
|
|
|
|
|
|
|
|
args := applyLogLevel([]string{"status"})
|
|
|
|
|
assert.Equal(t, []string{"status"}, args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_ApplyLogLevel_Ugly(t *testing.T) {
|
|
|
|
|
defer core.SetLevel(core.LevelInfo)
|
|
|
|
|
|
|
|
|
|
args := applyLogLevel([]string{"version", "-q"})
|
|
|
|
|
assert.Equal(t, []string{"version"}, args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_StartupArgs_Good(t *testing.T) {
|
|
|
|
|
defer core.SetLevel(core.LevelInfo)
|
|
|
|
|
|
|
|
|
|
withArgs(t, "core-agent", "--debug", "check")
|
|
|
|
|
args := startupArgs()
|
|
|
|
|
assert.Equal(t, []string{"check"}, args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_StartupArgs_Bad(t *testing.T) {
|
|
|
|
|
defer core.SetLevel(core.LevelInfo)
|
|
|
|
|
|
|
|
|
|
withArgs(t, "core-agent", "status")
|
|
|
|
|
args := startupArgs()
|
|
|
|
|
assert.Equal(t, []string{"status"}, args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_StartupArgs_Ugly(t *testing.T) {
|
|
|
|
|
defer core.SetLevel(core.LevelInfo)
|
|
|
|
|
|
|
|
|
|
withArgs(t, "core-agent", "version", "-q")
|
|
|
|
|
args := startupArgs()
|
|
|
|
|
assert.Equal(t, []string{"version"}, args)
|
|
|
|
|
}
|
2026-03-27 17:55:06 +00:00
|
|
|
|
2026-03-30 21:30:49 +00:00
|
|
|
func TestCommands_RegisterApplicationCommands_Good(t *testing.T) {
|
2026-03-27 17:55:06 +00:00
|
|
|
c := newTestCore(t)
|
|
|
|
|
cmds := c.Commands()
|
|
|
|
|
assert.Contains(t, cmds, "version")
|
|
|
|
|
assert.Contains(t, cmds, "check")
|
|
|
|
|
assert.Contains(t, cmds, "env")
|
2026-03-31 11:10:27 +00:00
|
|
|
assert.Contains(t, cmds, "mcp")
|
|
|
|
|
assert.Contains(t, cmds, "serve")
|
2026-03-27 17:55:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_Version_Good(t *testing.T) {
|
|
|
|
|
c := newTestCore(t)
|
2026-03-30 16:40:53 +00:00
|
|
|
agentpkg.Version = "0.8.0"
|
2026-03-30 00:00:33 +00:00
|
|
|
t.Cleanup(func() {
|
2026-03-30 16:40:53 +00:00
|
|
|
agentpkg.Version = ""
|
2026-03-30 00:00:33 +00:00
|
|
|
})
|
2026-03-27 17:55:06 +00:00
|
|
|
|
|
|
|
|
r := c.Cli().Run("version")
|
|
|
|
|
assert.True(t, r.OK)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 00:00:33 +00:00
|
|
|
func TestCommands_VersionDev_Bad(t *testing.T) {
|
2026-03-27 17:55:06 +00:00
|
|
|
c := newTestCore(t)
|
2026-03-30 16:40:53 +00:00
|
|
|
agentpkg.Version = ""
|
2026-03-27 17:55:06 +00:00
|
|
|
c.App().Version = "dev"
|
|
|
|
|
|
|
|
|
|
r := c.Cli().Run("version")
|
|
|
|
|
assert.True(t, r.OK)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_Check_Good(t *testing.T) {
|
|
|
|
|
c := newTestCore(t)
|
|
|
|
|
|
|
|
|
|
r := c.Cli().Run("check")
|
|
|
|
|
assert.True(t, r.OK)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 20:12:39 +00:00
|
|
|
func TestCommands_Check_Good_BranchWorkspaceCount(t *testing.T) {
|
|
|
|
|
c := newTestCore(t)
|
|
|
|
|
|
|
|
|
|
ws := core.JoinPath(agentic.WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
|
|
|
|
|
assert.True(t, agentic.LocalFs().EnsureDir(agentic.WorkspaceRepoDir(ws)).OK)
|
|
|
|
|
assert.True(t, agentic.LocalFs().EnsureDir(agentic.WorkspaceMetaDir(ws)).OK)
|
|
|
|
|
assert.True(t, agentic.LocalFs().Write(core.JoinPath(ws, "status.json"), core.JSONMarshalString(agentic.WorkspaceStatus{
|
|
|
|
|
Status: "running",
|
|
|
|
|
Repo: "go-io",
|
|
|
|
|
Agent: "codex",
|
|
|
|
|
})).OK)
|
|
|
|
|
|
|
|
|
|
output := captureStdout(t, func() {
|
|
|
|
|
r := c.Cli().Run("check")
|
|
|
|
|
assert.True(t, r.OK)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
assert.Contains(t, output, "1 workspaces")
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 17:55:06 +00:00
|
|
|
func TestCommands_Env_Good(t *testing.T) {
|
|
|
|
|
c := newTestCore(t)
|
|
|
|
|
|
|
|
|
|
r := c.Cli().Run("env")
|
|
|
|
|
assert.True(t, r.OK)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-31 11:10:27 +00:00
|
|
|
func TestCommands_MCPService_Good(t *testing.T) {
|
|
|
|
|
c := core.New(
|
|
|
|
|
core.WithOption("name", "core-agent"),
|
|
|
|
|
core.WithService(registerMCPService),
|
|
|
|
|
)
|
|
|
|
|
registerApplicationCommands(c)
|
|
|
|
|
|
|
|
|
|
service, err := (applicationCommandSet{coreApp: c}).mcpService()
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.NotNil(t, service)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_MCPService_Bad(t *testing.T) {
|
|
|
|
|
_, err := (applicationCommandSet{coreApp: newTestCore(t)}).mcpService()
|
|
|
|
|
assert.EqualError(t, err, "main.mcpService: mcp service not registered")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_MCPService_Ugly(t *testing.T) {
|
|
|
|
|
c := core.New(core.WithOption("name", "core-agent"))
|
|
|
|
|
assert.True(t, c.RegisterService("mcp", "invalid").OK)
|
|
|
|
|
|
|
|
|
|
_, err := (applicationCommandSet{coreApp: c}).mcpService()
|
|
|
|
|
assert.EqualError(t, err, "main.mcpService: mcp service has invalid type")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_ServeAddress_Good(t *testing.T) {
|
|
|
|
|
c := newTestCore(t)
|
|
|
|
|
|
|
|
|
|
addr := (applicationCommandSet{coreApp: c}).serveAddress(core.NewOptions(
|
|
|
|
|
core.Option{Key: "addr", Value: "0.0.0.0:9201"},
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, "0.0.0.0:9201", addr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_ServeAddress_Bad(t *testing.T) {
|
|
|
|
|
c := newTestCore(t)
|
|
|
|
|
t.Setenv("CORE_AGENT_HTTP_ADDR", "")
|
|
|
|
|
|
|
|
|
|
addr := (applicationCommandSet{coreApp: c}).serveAddress(core.NewOptions())
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, "127.0.0.1:9101", addr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCommands_ServeAddress_Ugly(t *testing.T) {
|
|
|
|
|
c := newTestCore(t)
|
|
|
|
|
|
|
|
|
|
addr := (applicationCommandSet{coreApp: c}).serveAddress(core.NewOptions(
|
|
|
|
|
core.Option{Key: "_arg", Value: "127.0.0.1:9911"},
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, "127.0.0.1:9911", addr)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 00:00:33 +00:00
|
|
|
func TestCommands_CliUnknown_Bad(t *testing.T) {
|
2026-03-27 17:55:06 +00:00
|
|
|
c := newTestCore(t)
|
|
|
|
|
r := c.Cli().Run("nonexistent")
|
|
|
|
|
assert.False(t, r.OK)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 00:00:33 +00:00
|
|
|
func TestCommands_CliBanner_Good(t *testing.T) {
|
2026-03-27 17:55:06 +00:00
|
|
|
c := newTestCore(t)
|
|
|
|
|
c.Cli().SetBanner(func(_ *core.Cli) string {
|
|
|
|
|
return "core-agent test"
|
|
|
|
|
})
|
|
|
|
|
r := c.Cli().Run()
|
|
|
|
|
_ = r
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 00:00:33 +00:00
|
|
|
func TestCommands_CliEmptyArgs_Ugly(t *testing.T) {
|
2026-03-27 17:55:06 +00:00
|
|
|
c := newTestCore(t)
|
|
|
|
|
r := c.Cli().Run()
|
|
|
|
|
_ = r
|
|
|
|
|
}
|