Files
2026-09-18 13:05:49 +08:00

95 lines
3.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package web
import (
"fmt"
"net/http/httptest"
"net/url"
"strings"
"testing"
)
// TestNewRowNumberingSkipsArchivedPKs 盯住「站点新建行的编号」。
//
// 编号不能只看 `MAX(places.src_pk)`:`entity_raw` 里还躺着导入时缺必填字段的 skipped 行
// (导出要把它们原样补回去,所以一直留着),那些号没有对应实体行却占着号位。
// 只看 places 的话,新行会拿到一个已经被留档占用的号 —— 导出时被当成「已存在的行」走 UPDATE,
// 于是继承对方 rond 自己写的那些列(ZRADIUS / ZTYPE_ / ZNOTE_…)。
//
// 这里造一条「只有留档、没有实体行」的 ZLOCATION,再分别走两条新建路径,断言编号绕开它。
func TestNewRowNumberingSkipsArchivedPKs(t *testing.T) {
f := newMovementFixture(t)
// 与 nextSrcPK 同一套口径,先算出「当前有效上限」
var cur int
if err := f.pg.QueryRowContext(f.ctx, `SELECT GREATEST(
(SELECT COALESCE(MAX(src_pk),0) FROM places WHERE dataset_id=$1),
COALESCE((coredata_meta->'entities'->'Location'->>'max')::int,0),
(SELECT COALESCE(MAX((raw->>'Z_PK')::numeric),0)::int FROM entity_raw
WHERE dataset_id=$1 AND entity='ZLOCATION' AND (raw->>'Z_PK') ~ '^[0-9]+$')
) FROM datasets WHERE id=$1`, f.dsID).Scan(&cur); err != nil {
t.Fatalf("算编号上限失败: %v", err)
}
stalePK := cur + 3
// 留档存的是整行 Core Data 记录,Z_PK 就在里面——nextSrcPK 正是靠它算上限
f.mustExec(t, `INSERT INTO entity_raw (dataset_id, entity, src_pk, raw, skipped)
VALUES ($1,'ZLOCATION',$2,$3::jsonb,true)`, f.dsID, stalePK,
fmt.Sprintf(`{"Z_PK":%d,"ZLATITUDE":30.0,"ZLONGITUDE":120.0}`, stalePK))
post := func(path string, form url.Values) {
t.Helper()
req := httptest.NewRequest("POST", path, strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req = req.WithContext(f.ctx)
rec := httptest.NewRecorder()
switch path {
case "/admin/edit/place":
f.srv.editPlaceCreate(rec, req)
case "/admin/photos/import":
f.srv.adminPhotosImport(rec, req)
default:
t.Fatalf("未接入的处理函数: %s", path)
}
if rec.Code >= 400 {
t.Fatalf("%s 返回 %d: %s", path, rec.Code, rec.Body.String())
}
}
srcPKOf := func(name string) int {
t.Helper()
var pk int
if err := f.pg.QueryRowContext(f.ctx, `SELECT src_pk FROM places
WHERE dataset_id=$1 AND name=$2`, f.dsID, name).Scan(&pk); err != nil {
t.Fatalf("地点 %q 没落库: %v", name, err)
}
return pk
}
// 路径一:后台「新增地点」
post("/admin/edit/place", url.Values{
"mode": {"new"}, "name": {"编号测试点-手工"}, "lat": {"30.11"}, "lon": {"120.11"},
})
if got := srcPKOf("编号测试点-手工"); got <= stalePK {
t.Errorf("手工新增的编号 %d 没绕开留档占用的 %d(旧实现会拿到 %d)", got, stalePK, cur+1)
}
// 路径二:照片导入(同一套规则)
post("/admin/photos/import", url.Values{
"n": {"1"}, "coord": {"wgs84"}, "keep_0": {"on"},
"lat_0": {"30.22"}, "lon_0": {"120.22"},
"arrival_0": {"2026-04-18T18:14"}, "name_0": {"编号测试点-照片"},
"country_0": {"CN"}, "timezone_0": {"Asia/Shanghai"},
})
if got := srcPKOf("编号测试点-照片"); got <= stalePK {
t.Errorf("照片导入的编号 %d 没绕开留档占用的 %d", got, stalePK)
}
// 留档那条本身还在(newSrcPK 绕开了它,就不该被清掉)
var n int
if err := f.pg.QueryRowContext(f.ctx, `SELECT count(*) FROM entity_raw
WHERE dataset_id=$1 AND entity='ZLOCATION' AND src_pk=$2`, f.dsID, stalePK).Scan(&n); err != nil {
t.Fatal(err)
}
if n != 1 {
t.Errorf("留档行被误清:期望 1 行,实际 %d", n)
}
}