package DB import ( "strconv" "strings" "testing" "git.ycl.pub/yl32940/TsDB2/DB/core/types" ) // TestParseModelMaxlenCap `maxlen` 声明超过单值上限的字符串列必须在建模阶段就被拒。 // // 这一层是唯一能拦它的地方: 声明超过 MaxInlineColumnWidth 的列落动态列, 而动态列【不保留 // 声明长度】(Flag 低 5 位必须为 0), 表一旦建出来, 那个 N 就不在盘上了 —— 事后再想校验 // "这一列声明的容量兑现得了吗"已无据可查。放过去的后果正是声明侧闸门要拦的那种失败: // 建表成功、跑了一阵、某天写入某个大值时才撞 ErrHeapPageTooLarge, 用户看不出因果。 func TestParseModelMaxlenCap(t *testing.T) { // 下面 tag 里的字面量必须与实现同步 (单值上限 = core.MaxBlobSize, 由 core 侧的 // 编译期断言钉住 types 那一份)。对不上就在这里编译失败, 而不是变成一个"碰巧还过"的测试。 const atCap, overCap = 16360, 16361 var ( _ = [1]struct{}{}[atCap-types.MaxStringSize] // 正好用满 = 上限 _ = [1]struct{}{}[overCap-types.MaxStringSize-1] // 比上限多一个字节 ) find := func(t *testing.T, mi *ModelInfo, col string) FieldDef { t.Helper() for _, fd := range mi.Fields { if fd.ColName == col { return fd } } t.Fatalf("模型里没有列 %s", col) return FieldDef{} } // 正好用满: 动态列装得下, 必须放行 —— 而且必须落成【动态列 + 宽度码 0】: // 这个宽度码是行内布局的唯一依据, 若它被写成非 0, FieldSize 就会按档位算宽度, // 整行字段从此错位 (比拒绝声明危险得多)。 t.Run("正好用满放行", func(t *testing.T) { type AtCap struct { BaseModel Full string `vrtx:"maxlen:16360"` } mi, err := ParseModel(&AtCap{}) if err != nil { t.Fatalf("声明 %d 字节应当放行: %v", atCap, err) } fd := find(t, mi, "Full") if fd.FieldType != types.FieldType_Dynamicbyte { t.Errorf("超过 %d 字节的声明应落动态列, 得到 %s", types.MaxInlineColumnWidth, types.TypeNameOf(fd.FieldType)) } if fd.Param() != 0 { t.Errorf("动态列的宽度码必须留在 0 (Flag 低 5 位), 得到 %d", fd.Param()) } }) // 多一个字节: 兑现不了, 必须拒。 t.Run("超过一个字节就拒", func(t *testing.T) { type OverCap struct { BaseModel Big string `vrtx:"maxlen:16361"` } _, err := ParseModel(&OverCap{}) if err == nil { t.Fatalf("声明 %d 字节必须被拒 (动态列装不下)", overCap) } // 报错要能直接定位: 哪个字段、用户写下的数、引擎能给的上限。 for _, want := range []string{"Big", strconv.Itoa(overCap), strconv.Itoa(types.MaxStringSize)} { if !strings.Contains(err.Error(), want) { t.Errorf("错误信息里缺少 %q: %v", want, err) } } }) // 闸门只管字符串列: 数值列的 maxlen 本来就被忽略 (用 Go 类型自动推断), 不该因此报错。 t.Run("数值列不受影响", func(t *testing.T) { type NumWide struct { BaseModel N int64 `vrtx:"maxlen:16361"` } if _, err := ParseModel(&NumWide{}); err != nil { t.Errorf("数值列的 maxlen 应当被忽略, 不该报错: %v", err) } }) }