Files
Agent-System/internal/server/test_helpers_test.go
T
weichen 784d852ac0 test(governance): PI Agent PG 全链路实测通过并固化运行条件
修复 runner 鉴权与 data/dev 工作区挂载,使用正式 main 工作流完成 intake→批准→推进。
2026-09-13 02:50:23 +00:00

165 lines
4.4 KiB
Go

package server_test
import (
"bytes"
"context"
"encoding/json"
"net"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
"github.com/jackc/pgx/v5/pgxpool"
"chat-agent-system/internal/auth"
"chat-agent-system/internal/config"
"chat-agent-system/internal/db"
"chat-agent-system/internal/workflowdef"
)
func loginTestAdmin(t *testing.T, handler http.Handler, cfg *config.Config) string {
t.Helper()
username := cfg.AdminUsername
password := cfg.AdminPassword
if username == "" {
username = "admin"
}
if password == "" {
password = "admin-secret-password-123"
}
body, _ := json.Marshal(map[string]string{
"username": username,
"password": password,
})
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", bytes.NewReader(body))
w := httptest.NewRecorder()
handler.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("admin login failed: %d %s", w.Code, w.Body.String())
}
var session auth.SessionInfo
if err := json.NewDecoder(w.Body).Decode(&session); err != nil {
t.Fatalf("decode login session: %v", err)
}
if session.Token == "" {
t.Fatal("expected non-empty session token")
}
return session.Token
}
func withBearerAuth(req *http.Request, token string) {
req.Header.Set("Authorization", "Bearer "+token)
}
func loginTestUser(t *testing.T, handler http.Handler, username, password string) string {
t.Helper()
body, _ := json.Marshal(map[string]string{
"username": username,
"password": password,
})
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", bytes.NewReader(body))
w := httptest.NewRecorder()
handler.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("login %s failed: %d %s", username, w.Code, w.Body.String())
}
var session auth.SessionInfo
if err := json.NewDecoder(w.Body).Decode(&session); err != nil {
t.Fatalf("decode login session: %v", err)
}
return session.Token
}
func withUserIDAuth(req *http.Request, token string) {
req.Header.Set("Authorization", "Bearer "+token)
}
func configFromTestDatabaseURL(t *testing.T) *config.Config {
t.Helper()
dsn := db.SkipIfNoTestDatabaseURL(t)
parsed, err := url.Parse(dsn)
if err != nil {
t.Fatalf("parse TEST_DATABASE_URL: %v", err)
}
host, portStr, splitErr := net.SplitHostPort(parsed.Host)
if splitErr != nil {
host = parsed.Host
portStr = "5432"
}
port, _ := strconv.Atoi(portStr)
user := parsed.User.Username()
password, _ := parsed.User.Password()
dbName := strings.TrimPrefix(parsed.Path, "/")
return &config.Config{
Env: "test",
DataDir: t.TempDir(),
AgentBackend: "stub",
AllowInMemory: false,
ContextDbHost: host,
ContextDbPort: port,
ContextDbUser: user,
ContextDbPassword: password,
ContextDbName: dbName,
AdminUsername: envOr("ADMIN_USERNAME", "admin"),
AdminPassword: envOr("ADMIN_PASSWORD", "admin-secret-password-123"),
}
}
func envOr(key, fallback string) string {
if v := strings.TrimSpace(os.Getenv(key)); v != "" {
return v
}
return fallback
}
func piAgentSharedDataDir(t *testing.T) string {
t.Helper()
if d := strings.TrimSpace(os.Getenv("DATA_DIR")); d != "" {
return d
}
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("getwd: %v", err)
}
for _, rel := range []string{".", "..", "../..", "../../.."} {
base := filepath.Clean(filepath.Join(cwd, rel))
for _, envName := range []string{"dev", "test"} {
candidate := filepath.Join(base, "data", envName)
ws := filepath.Join(candidate, "workspaces")
if st, statErr := os.Stat(ws); statErr == nil && st.IsDir() {
return candidate
}
}
}
t.Skip("shared pi-agent DATA_DIR not found (mount data/test/workspaces or data/dev/workspaces)")
return ""
}
func seedOfficialWorkflowManifest(t *testing.T, pool *pgxpool.Pool, workflowKey string) {
t.Helper()
filename, ok := workflowdef.V2ManifestFiles[workflowKey]
if !ok {
t.Fatalf("unknown official workflow key %q", workflowKey)
}
def, err := workflowdef.LoadManifestDefinition(filename)
if err != nil {
t.Fatalf("load manifest %s: %v", filename, err)
}
wfStore := workflowdef.NewStore(pool)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := wfStore.UpsertPublishedSeed(ctx, workflowdef.CreateDefinitionInput{
Key: workflowKey,
Name: workflowdef.OfficialWorkflowName(workflowKey),
Definition: def,
}, 1); err != nil {
t.Fatalf("seed official workflow %s: %v", workflowKey, err)
}
}