xworkmate-bridge/internal/acp/gateway_test.go

225 lines
7.1 KiB
Go

package acp
import (
"path/filepath"
"testing"
"xworkmate-bridge/internal/gatewayruntime"
"xworkmate-bridge/internal/shared"
)
func TestApplyProductionGatewayRoutingPreservesGatewayURLPath(t *testing.T) {
t.Setenv("GATEWAY_RPC_URL", "ws://127.0.0.1:18789/gateway/openclaw")
server := NewServer()
request := applyProductionGatewayRouting(
server,
gatewayruntime.ConnectRequest{
Mode: "openclaw",
Endpoint: gatewayruntime.Endpoint{
Host: "xworkmate-bridge.svc.plus",
Port: 443,
TLS: true,
},
},
)
if request.Endpoint.Host != "127.0.0.1" {
t.Fatalf("expected gateway host from env, got %#v", request.Endpoint)
}
if request.Endpoint.Port != 18789 {
t.Fatalf("expected gateway port from env, got %#v", request.Endpoint)
}
if request.Endpoint.TLS {
t.Fatalf("expected plaintext local gateway endpoint, got %#v", request.Endpoint)
}
if request.Endpoint.Path != "/gateway/openclaw" {
t.Fatalf("expected gateway URL path to be preserved, got %#v", request.Endpoint)
}
}
func TestApplyProductionGatewayRoutingDefaultsOpenClawEndpoint(t *testing.T) {
t.Setenv("GATEWAY_RPC_URL", "")
t.Setenv("BRIDGE_CONFIG_PATH", filepath.Join(t.TempDir(), "missing-config.yaml"))
server := NewServer()
request := applyProductionGatewayRouting(
server,
gatewayruntime.ConnectRequest{Mode: "openclaw"},
)
if request.Endpoint.Host != "127.0.0.1" {
t.Fatalf("expected built-in gateway host, got %#v", request.Endpoint)
}
if request.Endpoint.Port != 18789 {
t.Fatalf("expected built-in gateway port, got %#v", request.Endpoint)
}
if request.Endpoint.TLS {
t.Fatalf("expected built-in gateway endpoint to use local plaintext, got %#v", request.Endpoint)
}
}
func TestSystemLogsConnectsProductionGatewayForStatus(t *testing.T) {
gateway := newAcpFakeOpenClawGateway(t)
defer gateway.Close()
t.Setenv("GATEWAY_RPC_URL", gateway.URL())
t.Setenv("BRIDGE_AUTH_TOKEN", "bridge-test-token")
t.Setenv("BRIDGE_CONFIG_PATH", filepath.Join(t.TempDir(), "missing-config.yaml"))
t.Setenv("XWORKMATE_BRIDGE_OPENCLAW_IDENTITY_PATH", filepath.Join(t.TempDir(), "openclaw-device.json"))
resetBridgeGatewayIdentityForTest()
t.Cleanup(resetBridgeGatewayIdentityForTest)
server := NewServer()
result, rpcErr := server.handleRequest(
shared.RPCRequest{
ID: "status",
Method: "system.logs",
Params: map[string]any{},
},
func(map[string]any) {},
)
if rpcErr != nil {
t.Fatalf("system.logs returned rpc error: %#v", rpcErr)
}
if got := result["gatewayStatus"]; got != "connected" {
t.Fatalf("expected gatewayStatus connected, got %#v", result)
}
if got := gateway.ConnectCount(); got != 1 {
t.Fatalf("expected one gateway connect attempt, got %d", got)
}
result, rpcErr = server.handleRequest(
shared.RPCRequest{
ID: "status-again",
Method: "system.logs",
Params: map[string]any{},
},
func(map[string]any) {},
)
if rpcErr != nil {
t.Fatalf("second system.logs returned rpc error: %#v", rpcErr)
}
if got := result["gatewayStatus"]; got != "connected" {
t.Fatalf("expected second gatewayStatus connected, got %#v", result)
}
if got := gateway.ConnectCount(); got != 1 {
t.Fatalf("expected connected status to reuse gateway session, got %d connect attempts", got)
}
}
func TestProductionGatewayReconnectsWithSharedTokenAfterDeviceTokenMismatch(t *testing.T) {
gateway := newAcpFakeOpenClawGateway(t)
defer gateway.Close()
gateway.rejectDeviceTokenOnce.Store(true)
identityPath := filepath.Join(t.TempDir(), "openclaw-device.json")
t.Setenv("GATEWAY_RPC_URL", gateway.URL())
t.Setenv("BRIDGE_AUTH_TOKEN", "bridge-test-token")
t.Setenv("BRIDGE_CONFIG_PATH", filepath.Join(t.TempDir(), "missing-config.yaml"))
t.Setenv("XWORKMATE_BRIDGE_OPENCLAW_IDENTITY_PATH", identityPath)
resetBridgeGatewayIdentityForTest()
t.Cleanup(resetBridgeGatewayIdentityForTest)
_ = newBridgeGatewayIdentity()
saveBridgeGatewayDeviceToken("stale-device-token")
server := NewServer()
result, rpcErr := server.handleRequest(
shared.RPCRequest{
ID: "status",
Method: "system.logs",
Params: map[string]any{},
},
func(map[string]any) {},
)
if rpcErr != nil {
t.Fatalf("system.logs returned rpc error: %#v", rpcErr)
}
if got := result["gatewayStatus"]; got != "connected" {
t.Fatalf("expected gatewayStatus connected after repair, got %#v", result)
}
if got := gateway.ConnectCount(); got != 2 {
t.Fatalf("expected stale device token retry with shared token, got %d connects", got)
}
resetBridgeGatewayIdentityForTest()
_, token := bridgeGatewayOpenClawCredentials()
if token != "device-token-1" {
t.Fatalf("expected repaired device token to be persisted, got %q", token)
}
}
func TestProductionGatewayReconnectPrefersAIWorkspaceToken(t *testing.T) {
gateway := newAcpFakeOpenClawGateway(t)
defer gateway.Close()
gateway.rejectDeviceTokenOnce.Store(true)
t.Setenv("GATEWAY_RPC_URL", gateway.URL())
t.Setenv("AI_WORKSPACE_AUTH_TOKEN", "ai-workspace-token")
t.Setenv("BRIDGE_AUTH_TOKEN", "bridge-test-token")
t.Setenv("BRIDGE_CONFIG_PATH", filepath.Join(t.TempDir(), "missing-config.yaml"))
t.Setenv("XWORKMATE_BRIDGE_OPENCLAW_IDENTITY_PATH", filepath.Join(t.TempDir(), "openclaw-device.json"))
resetBridgeGatewayIdentityForTest()
t.Cleanup(resetBridgeGatewayIdentityForTest)
_ = newBridgeGatewayIdentity()
saveBridgeGatewayDeviceToken("stale-device-token")
server := NewServer()
result, rpcErr := server.handleRequest(
shared.RPCRequest{
ID: "status",
Method: "system.logs",
Params: map[string]any{},
},
func(map[string]any) {},
)
if rpcErr != nil {
t.Fatalf("system.logs returned rpc error: %#v", rpcErr)
}
if got := result["gatewayStatus"]; got != "connected" {
t.Fatalf("expected gatewayStatus connected after AI workspace token repair, got %#v", result)
}
if got := gateway.ConnectCount(); got != 2 {
t.Fatalf("expected stale device token retry with AI workspace token, got %d connects", got)
}
}
func TestProductionGatewayDoesNotUseInternalServiceTokenFallback(t *testing.T) {
gateway := newAcpFakeOpenClawGateway(t)
defer gateway.Close()
gateway.rejectDeviceTokenOnce.Store(true)
t.Setenv("GATEWAY_RPC_URL", gateway.URL())
t.Setenv("AI_WORKSPACE_AUTH_TOKEN", "")
t.Setenv("BRIDGE_AUTH_TOKEN", "")
t.Setenv("INTERNAL_SERVICE_TOKEN", "bridge-test-token")
t.Setenv("BRIDGE_CONFIG_PATH", filepath.Join(t.TempDir(), "missing-config.yaml"))
t.Setenv("XWORKMATE_BRIDGE_OPENCLAW_IDENTITY_PATH", filepath.Join(t.TempDir(), "openclaw-device.json"))
resetBridgeGatewayIdentityForTest()
t.Cleanup(resetBridgeGatewayIdentityForTest)
_ = newBridgeGatewayIdentity()
saveBridgeGatewayDeviceToken("stale-device-token")
server := NewServer()
result, rpcErr := server.handleRequest(
shared.RPCRequest{
ID: "status",
Method: "system.logs",
Params: map[string]any{},
},
func(map[string]any) {},
)
if rpcErr != nil {
t.Fatalf("system.logs returned rpc error: %#v", rpcErr)
}
if got := result["gatewayStatus"]; got != "disconnected" {
t.Fatalf("expected gatewayStatus disconnected without AI workspace token, got %#v", result)
}
if got := gateway.ConnectCount(); got != 1 {
t.Fatalf("expected no retry with internal token, got %d connects", got)
}
}