4adc1398f6
- шаг «База bj»: перенос на сервер PostgreSQL организации (проверка подключения, версии, прав, пустой базы; pg_dump → psql; сверка числа строк по таблицам; переключение и перезапуск); прежняя база — запасная копия; резервные копии: дамп внешней базы по её подключению, восстановление её не трогает - все формы: пустые видимые обязательные поля называются по имени и подсвечиваются; DEPO — и на сервере - «Обновить/Создать канал»: в фоне bj, ход по этапам с таймером (и после перезагрузки страницы), переходы заблокированы до конца, в конце проверка, что шлюз загрузил канал; состояние ИШ во время записи — без очереди к root-обработчику (страница больше не висит на «Проверяю…») Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
64 lines
2.3 KiB
Go
64 lines
2.3 KiB
Go
package lkgateway
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
// Перенос базы bj на живом PostgreSQL: BJ_PGMOVE_SRC — строка подключения исходной базы, BJ_PGMOVE_DST — пустой
|
|
// целевой (для проверки допускается этот же сервер). Без переменных — пропуск.
|
|
func TestPGMoveLive(t *testing.T) {
|
|
srcDSN, dstDSN := os.Getenv("BJ_PGMOVE_SRC"), os.Getenv("BJ_PGMOVE_DST")
|
|
if srcDSN == "" || dstDSN == "" {
|
|
t.Skip("нет BJ_PGMOVE_SRC/BJ_PGMOVE_DST")
|
|
}
|
|
u, _ := url.Parse(dstDSN)
|
|
pw, _ := u.User.Password()
|
|
tg := pgTarget{Host: u.Hostname(), Port: u.Port(), DB: u.Path[1:], User: u.User.Username(), Password: pw, SSL: u.Query().Get("sslmode")}
|
|
ctx := context.Background()
|
|
src, err := pgInspect(ctx, srcDSN, false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, why := pgCheckTarget(ctx, src, tg); why != "" {
|
|
t.Fatal(why)
|
|
}
|
|
if err := pgCopy(ctx, srcDSN, tg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
s, _ := pgInspect(ctx, srcDSN, true)
|
|
d, err := pgInspect(ctx, tg.dsn(true), true)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := pgCompare(s, d); len(diff) > 0 {
|
|
t.Fatalf("расхождения: %v", diff)
|
|
}
|
|
var n int64
|
|
for _, c := range s.Rows {
|
|
n += c
|
|
}
|
|
t.Logf("перенесено: таблиц %d, строк %d (PostgreSQL %s → %s)", len(s.Tables), n, s.Version, d.Version)
|
|
if _, why := pgCheckTarget(ctx, src, tg); why == "" {
|
|
t.Fatal("после переноса база не пустая — повторная проверка должна отказать")
|
|
}
|
|
}
|
|
|
|
func TestPGTargetForm(t *testing.T) {
|
|
tg := pgTarget{Host: "db.local", Port: "5432", DB: "bj", User: "bj", Password: "p@ss:w/rd", SSL: "require"}
|
|
if got := tg.dsn(true); got != "postgres://bj:p%40ss%3Aw%2Frd@db.local:5432/bj?sslmode=require" {
|
|
t.Errorf("dsn: %s", got)
|
|
}
|
|
if s, p := pgSplitDSN(tg.dsn(true)); p != "p@ss:w/rd" || s != "postgres://bj@db.local:5432/bj?sslmode=require" {
|
|
t.Errorf("split: %s / %s", s, p)
|
|
}
|
|
if !pgDSNLocal("postgres://bj:x@127.0.0.1:5432/bj") || pgDSNLocal("postgres://bj:x@10.0.0.5:5432/bj") {
|
|
t.Error("pgDSNLocal")
|
|
}
|
|
if d := pgCompare(pgInfo{Tables: []string{"a.t"}, Rows: map[string]int64{"a.t": 3}}, pgInfo{Rows: map[string]int64{"a.t": 2}}); len(d) != 1 {
|
|
t.Errorf("сверка: %v", d)
|
|
}
|
|
}
|