refactor(infra): split de drivers pesados a subpaquetes + fix TestSSEHandler
Mueve duckdb_open, clickhouse_open, postgres_open, matrix_* y keyring_token_store
del paquete monolitico functions/infra a subpaquetes propios
(functions/infra/{duckdb,clickhouse,postgres,matrix,keyring}). El paquete infra ya
no importa los drivers (go-duckdb, clickhouse-go, pgx, mautrix, go-keyring), por lo
que las apps que solo usan funciones ligeras (process, cron, http, sqlite) dejan de
arrastrarlos. Reduccion de binarios: dag_engine 72->10MB, registry_api 70->8.7MB,
services_api 70->9MB, call_monitor 68->6.6MB, sqlite_api 70->8.9MB.
Los IDs del registry se mantienen estables (domain: infra en frontmatter). Se
preservan los build tags goolm/libolm de matrix_crypto_init.
Tambien corrige TestSSEHandler: el test leia el body con un unico Read() que con
HTTP chunked solo capturaba el primer evento; ahora usa io.ReadAll hasta EOF.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
package matrix
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// whoamiHandler devuelve un handler httptest que simula /_matrix/client/v3/account/whoami.
|
||||
// Si statusCode != 200, devuelve un RespError de mautrix.
|
||||
func whoamiHandler(t *testing.T, statusCode int, userID, deviceID string) http.HandlerFunc {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if statusCode != http.StatusOK {
|
||||
// mautrix espera JSON con errcode/error para errores Matrix
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(statusCode)
|
||||
_ = json.NewEncoder(w).Encode(map[string]string{
|
||||
"errcode": "M_UNKNOWN_TOKEN",
|
||||
"error": "Invalid macaroon passed.",
|
||||
})
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_ = json.NewEncoder(w).Encode(map[string]string{
|
||||
"user_id": userID,
|
||||
"device_id": deviceID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatrixClientInit(t *testing.T) {
|
||||
t.Run("HomeserverURL invalido", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
cfg := MatrixClientInitConfig{
|
||||
HomeserverURL: "not-a-url",
|
||||
UserID: "@user:server",
|
||||
AccessToken: "mxat_test",
|
||||
StoreDir: tmpDir,
|
||||
}
|
||||
_, err := MatrixClientInit(cfg)
|
||||
if err == nil {
|
||||
t.Fatal("esperaba error con HomeserverURL invalido, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "HomeserverURL") {
|
||||
t.Errorf("error deberia mencionar HomeserverURL, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("UserID format invalido", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
cfg := MatrixClientInitConfig{
|
||||
HomeserverURL: "https://matrix.example.com",
|
||||
UserID: "egutierrez",
|
||||
AccessToken: "mxat_test",
|
||||
StoreDir: tmpDir,
|
||||
}
|
||||
_, err := MatrixClientInit(cfg)
|
||||
if err == nil {
|
||||
t.Fatal("esperaba error con UserID invalido, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "UserID") {
|
||||
t.Errorf("error deberia mencionar UserID, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DeviceID vacio Whoami exitoso", func(t *testing.T) {
|
||||
const testUserID = "@egutierrez:test.matrix.org"
|
||||
const testDeviceID = "ABCDEF1234"
|
||||
|
||||
srv := httptest.NewServer(whoamiHandler(t, http.StatusOK, testUserID, testDeviceID))
|
||||
defer srv.Close()
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
cfg := MatrixClientInitConfig{
|
||||
HomeserverURL: srv.URL,
|
||||
UserID: testUserID,
|
||||
AccessToken: "mxat_valid_token",
|
||||
DeviceID: "", // fuerza Whoami
|
||||
StoreDir: tmpDir,
|
||||
}
|
||||
res, err := MatrixClientInit(cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("esperaba nil error, got: %v", err)
|
||||
}
|
||||
if res.Client == nil {
|
||||
t.Fatal("Client es nil")
|
||||
}
|
||||
if string(res.Client.DeviceID) != testDeviceID {
|
||||
t.Errorf("DeviceID: got %q, want %q", res.Client.DeviceID, testDeviceID)
|
||||
}
|
||||
if string(res.Client.UserID) != testUserID {
|
||||
t.Errorf("UserID: got %q, want %q", res.Client.UserID, testUserID)
|
||||
}
|
||||
if res.Client.AccessToken != "mxat_valid_token" {
|
||||
t.Errorf("AccessToken: got %q, want %q", res.Client.AccessToken, "mxat_valid_token")
|
||||
}
|
||||
if res.StorePath == "" {
|
||||
t.Error("StorePath no puede estar vacio")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Whoami 401 token invalido", func(t *testing.T) {
|
||||
srv := httptest.NewServer(whoamiHandler(t, http.StatusUnauthorized, "", ""))
|
||||
defer srv.Close()
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
cfg := MatrixClientInitConfig{
|
||||
HomeserverURL: srv.URL,
|
||||
UserID: "@egutierrez:test.matrix.org",
|
||||
AccessToken: "mxat_expired",
|
||||
DeviceID: "", // fuerza Whoami
|
||||
StoreDir: tmpDir,
|
||||
}
|
||||
_, err := MatrixClientInit(cfg)
|
||||
if err == nil {
|
||||
t.Fatal("esperaba error con token invalido, got nil")
|
||||
}
|
||||
// Debe mencionar token invalido o M_UNKNOWN_TOKEN
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, "UNKNOWN_TOKEN") && !strings.Contains(errStr, "token") && !strings.Contains(errStr, "Whoami") {
|
||||
t.Errorf("error deberia mencionar token/Whoami, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("EnableCrypto true devuelve error not implemented", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
cfg := MatrixClientInitConfig{
|
||||
HomeserverURL: "https://matrix.example.com",
|
||||
UserID: "@user:matrix.example.com",
|
||||
AccessToken: "mxat_test",
|
||||
StoreDir: tmpDir,
|
||||
EnableCrypto: true,
|
||||
}
|
||||
_, err := MatrixClientInit(cfg)
|
||||
if err == nil {
|
||||
t.Fatal("esperaba error con EnableCrypto=true, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "not implemented") {
|
||||
t.Errorf("error deberia mencionar 'not implemented', got: %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "0150") {
|
||||
t.Errorf("error deberia mencionar issue 0150, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("StoreDir se crea con permisos 0700", func(t *testing.T) {
|
||||
if os.Getenv("GOOS") == "windows" {
|
||||
t.Skip("permisos Unix no aplican en Windows")
|
||||
}
|
||||
|
||||
const testUserID = "@egutierrez:test.matrix.org"
|
||||
const testDeviceID = "TESTDEVICE01"
|
||||
|
||||
srv := httptest.NewServer(whoamiHandler(t, http.StatusOK, testUserID, testDeviceID))
|
||||
defer srv.Close()
|
||||
|
||||
base := t.TempDir()
|
||||
// StoreDir que no existe aun — debe crearse
|
||||
storeDir := filepath.Join(base, "matrix_state", "egutierrez")
|
||||
|
||||
cfg := MatrixClientInitConfig{
|
||||
HomeserverURL: srv.URL,
|
||||
UserID: testUserID,
|
||||
AccessToken: "mxat_valid",
|
||||
DeviceID: testDeviceID,
|
||||
StoreDir: storeDir,
|
||||
}
|
||||
res, err := MatrixClientInit(cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("esperaba nil error, got: %v", err)
|
||||
}
|
||||
if res.StorePath != storeDir {
|
||||
t.Errorf("StorePath: got %q, want %q", res.StorePath, storeDir)
|
||||
}
|
||||
|
||||
info, err := os.Stat(storeDir)
|
||||
if err != nil {
|
||||
t.Fatalf("StoreDir no fue creado: %v", err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
t.Error("StoreDir no es un directorio")
|
||||
}
|
||||
// Verificar permisos 0700 (solo propietario)
|
||||
mode := info.Mode().Perm()
|
||||
if mode != 0700 {
|
||||
t.Errorf("permisos StoreDir: got %04o, want 0700", mode)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user