필드 테스트를 위해 edge OpenAI-compatible 경로와 node adapter 설정을 확장하고, Jenkins 바이너리 빌드 및 control-plane/web compose 배포 구성을 함께 정리한다.
223 lines
5.4 KiB
Go
223 lines
5.4 KiB
Go
package node_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
edgenode "iop/apps/edge/internal/node"
|
|
"iop/packages/config"
|
|
)
|
|
|
|
func TestBuildConfigPayload_OllamaEnabled(t *testing.T) {
|
|
rec := &edgenode.NodeRecord{
|
|
ID: "node-1",
|
|
Alias: "test",
|
|
Token: "token",
|
|
Adapters: config.AdaptersConf{
|
|
Ollama: config.OllamaConf{
|
|
Enabled: true,
|
|
BaseURL: "http://localhost:11434",
|
|
ContextSize: 262144,
|
|
},
|
|
},
|
|
Runtime: config.RuntimeConf{
|
|
Concurrency: 4,
|
|
WorkspaceRoot: "/tmp/ws",
|
|
},
|
|
}
|
|
|
|
payload, err := edgenode.BuildConfigPayload(rec)
|
|
if err != nil {
|
|
t.Fatalf("BuildConfigPayload failed: %v", err)
|
|
}
|
|
|
|
if payload.Runtime == nil {
|
|
t.Fatal("expected runtime config, got nil")
|
|
}
|
|
if payload.Runtime.Concurrency != 4 {
|
|
t.Errorf("expected concurrency 4, got %d", payload.Runtime.Concurrency)
|
|
}
|
|
|
|
if len(payload.Adapters) < 2 {
|
|
t.Fatalf("expected at least 2 adapters, got %d", len(payload.Adapters))
|
|
}
|
|
|
|
mockFound := false
|
|
ollamaFound := false
|
|
for _, a := range payload.Adapters {
|
|
if a.Type == "mock" {
|
|
mockFound = true
|
|
}
|
|
if a.Type == "ollama" {
|
|
ollamaFound = true
|
|
ollamaCfg := a.GetOllama()
|
|
if ollamaCfg == nil {
|
|
t.Fatal("expected ollama adapter config")
|
|
}
|
|
if ollamaCfg.BaseUrl != "http://localhost:11434" {
|
|
t.Errorf("expected ollama base url %q, got %q", "http://localhost:11434", ollamaCfg.BaseUrl)
|
|
}
|
|
if ollamaCfg.ContextSize != 262144 {
|
|
t.Errorf("expected ollama context size %d, got %d", 262144, ollamaCfg.ContextSize)
|
|
}
|
|
}
|
|
}
|
|
if !mockFound {
|
|
t.Fatal("expected mock adapter")
|
|
}
|
|
if !ollamaFound {
|
|
t.Fatal("expected ollama adapter when enabled")
|
|
}
|
|
}
|
|
|
|
func TestBuildConfigPayload_CLIProfiles(t *testing.T) {
|
|
rec := &edgenode.NodeRecord{
|
|
ID: "node-1",
|
|
Alias: "test",
|
|
Token: "token",
|
|
Adapters: config.AdaptersConf{
|
|
CLI: config.CLIConf{
|
|
Enabled: true,
|
|
Profiles: map[string]config.CLIProfileConf{
|
|
"default": {
|
|
Command: "echo",
|
|
Args: []string{"hello"},
|
|
Env: []string{"FOO=bar"},
|
|
Persistent: false,
|
|
Terminal: true,
|
|
ResponseIdleTimeoutMS: 5000,
|
|
StartupIdleTimeoutMS: 10000,
|
|
OutputFormat: "plain",
|
|
Mode: "implicit",
|
|
ResumeArgs: []string{"--resume"},
|
|
CompletionMarker: config.CompletionMarkerConf{
|
|
Line: "DONE",
|
|
Regex: "^DONE$",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Runtime: config.RuntimeConf{
|
|
WorkspaceRoot: "/tmp/ws",
|
|
},
|
|
}
|
|
|
|
payload, err := edgenode.BuildConfigPayload(rec)
|
|
if err != nil {
|
|
t.Fatalf("BuildConfigPayload failed: %v", err)
|
|
}
|
|
|
|
cliFound := false
|
|
for _, a := range payload.Adapters {
|
|
if a.Type == "cli" {
|
|
cliFound = true
|
|
cliCfg := a.GetCli()
|
|
if cliCfg == nil {
|
|
t.Fatal("expected cli adapter config")
|
|
}
|
|
if len(cliCfg.Profiles) != 1 {
|
|
t.Fatalf("expected 1 cli profile, got %d", len(cliCfg.Profiles))
|
|
}
|
|
p, ok := cliCfg.Profiles["default"]
|
|
if !ok {
|
|
t.Fatal("expected default profile")
|
|
}
|
|
if p.Command != "echo" {
|
|
t.Errorf("expected command %q, got %q", "echo", p.Command)
|
|
}
|
|
if len(p.Args) != 1 || p.Args[0] != "hello" {
|
|
t.Errorf("expected args [hello], got %v", p.Args)
|
|
}
|
|
if p.OutputFormat != "plain" {
|
|
t.Errorf("expected format %q, got %q", "plain", p.OutputFormat)
|
|
}
|
|
if cm := p.CompletionMarker; cm == nil || cm.Line != "DONE" {
|
|
t.Errorf("expected completion marker line %q, got %v", "DONE", cm)
|
|
}
|
|
}
|
|
}
|
|
if !cliFound {
|
|
t.Fatal("expected cli adapter when enabled")
|
|
}
|
|
}
|
|
|
|
func TestBuildConfigPayload_CLIProfileOpencodeSSEMode(t *testing.T) {
|
|
rec := &edgenode.NodeRecord{
|
|
ID: "node-1",
|
|
Alias: "test",
|
|
Token: "token",
|
|
Adapters: config.AdaptersConf{
|
|
CLI: config.CLIConf{
|
|
Enabled: true,
|
|
Profiles: map[string]config.CLIProfileConf{
|
|
"opencode": {
|
|
Command: "/usr/local/bin/opencode",
|
|
Args: []string{"--model", "m"},
|
|
Mode: "opencode-sse",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Runtime: config.RuntimeConf{WorkspaceRoot: "/tmp/ws"},
|
|
}
|
|
|
|
payload, err := edgenode.BuildConfigPayload(rec)
|
|
if err != nil {
|
|
t.Fatalf("BuildConfigPayload failed: %v", err)
|
|
}
|
|
|
|
var found bool
|
|
for _, a := range payload.Adapters {
|
|
if a.Type != "cli" {
|
|
continue
|
|
}
|
|
cli := a.GetCli()
|
|
if cli == nil {
|
|
t.Fatal("expected cli config")
|
|
}
|
|
p, ok := cli.Profiles["opencode"]
|
|
if !ok {
|
|
t.Fatal("expected opencode profile in payload")
|
|
}
|
|
if p.Mode != "opencode-sse" {
|
|
t.Errorf("mode: got %q, want %q", p.Mode, "opencode-sse")
|
|
}
|
|
if len(p.Args) != 2 || p.Args[0] != "--model" || p.Args[1] != "m" {
|
|
t.Errorf("args: got %v", p.Args)
|
|
}
|
|
found = true
|
|
}
|
|
if !found {
|
|
t.Fatal("expected cli adapter in payload")
|
|
}
|
|
}
|
|
|
|
func TestBuildConfigPayload_MockAlwaysPresent(t *testing.T) {
|
|
rec := &edgenode.NodeRecord{
|
|
ID: "node-1",
|
|
Alias: "test",
|
|
Token: "token",
|
|
Adapters: config.AdaptersConf{
|
|
Ollama: config.OllamaConf{Enabled: false},
|
|
Vllm: config.VllmConf{Enabled: false},
|
|
CLI: config.CLIConf{Enabled: false},
|
|
},
|
|
Runtime: config.RuntimeConf{
|
|
WorkspaceRoot: "/tmp/ws",
|
|
},
|
|
}
|
|
|
|
payload, err := edgenode.BuildConfigPayload(rec)
|
|
if err != nil {
|
|
t.Fatalf("BuildConfigPayload failed: %v", err)
|
|
}
|
|
|
|
if len(payload.Adapters) < 1 {
|
|
t.Fatalf("expected at least 1 adapter, got %d", len(payload.Adapters))
|
|
}
|
|
|
|
first := payload.Adapters[0]
|
|
if first.Type != "mock" {
|
|
t.Errorf("expected first adapter type %q, got %q", "mock", first.Type)
|
|
}
|
|
}
|