package core import ( "strings" "testing" "git.ycl.pub/yl32940/TsDB2/DB/core/page" "git.ycl.pub/yl32940/TsDB2/DB/core/types" ) // TestHeaderCommentAutoIntro 新建库未提供介绍时, Comment 默认写入 VersionComment // (当前版本的功能介绍与修复点)。 func TestHeaderCommentAutoIntro(t *testing.T) { db := fixOpenDB(t) c := db.Comment() if c == "" { t.Fatal("新建库的 Comment 不应为空") } if c != VersionComment { t.Fatalf("新建库的 Comment 应等于 VersionComment, 得到 %q", c) } if !strings.Contains(c, "v11") { t.Fatalf("默认介绍应含版本号 %q", c[:min(64, len(c))]) } } // TestHeaderCommentSetAndReopen SetComment 写入后经关闭重开仍能原样读回 (含多字节字符)。 func TestHeaderCommentSetAndReopen(t *testing.T) { path := t.TempDir() + "/comment.db" db, err := Open(path) if err != nil { t.Fatalf("open: %v", err) } db.SetAutoCommitDelay(0) const want = "hello 数据库" if err := db.SetComment(want); err != nil { t.Fatalf("SetComment: %v", err) } if c := db.Comment(); c != want { t.Fatalf("SetComment 后 Comment()=%q, 想要 %q", c, want) } if err := db.Close(); err != nil { t.Fatalf("close: %v", err) } db2, err := Open(path) if err != nil { t.Fatalf("reopen: %v", err) } defer db2.Close() if c := db2.Comment(); c != want { t.Fatalf("重开后 Comment()=%q, 想要 %q", c, want) } } // TestHeaderCommentTooLong 超过介绍区容量 (PageSize4K-844 = 3252 字节) 必须报错, // 而不是静默截断; 恰好 3252 字节允许。 func TestHeaderCommentTooLong(t *testing.T) { db := fixOpenDB(t) before := db.Comment() const cap1 = PageSize4K - 332 // 介绍区实际容量 (3764B) if err := db.SetComment(strings.Repeat("x", cap1+1)); err == nil { t.Fatalf("SetComment(%d 字节) 应报错", cap1+1) } if c := db.Comment(); c != before { t.Fatalf("超长写入失败后 Comment 被改写成 %q", c) } if err := db.SetComment(strings.Repeat("x", cap1)); err != nil { t.Fatalf("SetComment(%d 字节, 恰好等于容量) 不应报错: %v", cap1, err) } if c := db.Comment(); len(c) != cap1 { t.Fatalf("恰好容量的写入后长度 = %d, 想要 %d", len(c), cap1) } } // TestHeaderCommentSurvivesTableOps 建时序表 / 插入 / 删除 / 提交后 Comment 不变。 func TestHeaderCommentSurvivesTableOps(t *testing.T) { db := fixOpenDB(t) before := db.Comment() tbl, err := db.CreateTable("tick", []types.FieldInfo{ {FieldType: types.FieldType_Uint64, FieldName: []byte("ts")}, {FieldType: types.FieldType_Float64, FieldName: []byte("price")}, }) if err != nil { t.Fatalf("建表: %v", err) } if _, err := tbl.CreateIndex("ts_tick", page.IndexTypeTime, []byte{0}); err != nil { t.Fatalf("建时序索引: %v", err) } for i := 1; i <= 50; i++ { if _, err := tbl.InsertRowWithID(uint64(i), []types.FieldValue{ {FieldName: []byte("ts"), Value: uint64(i * 10)}, {FieldName: []byte("price"), Value: float64(i) + 0.5}, }); err != nil { t.Fatalf("插入 %d: %v", i, err) } } if err := db.Commit(); err != nil { t.Fatalf("commit: %v", err) } // 按时间键删几行 for _, ts := range []uint64{100, 200, 300} { key, err := tbl.BuildIndexKey("ts_tick", ts) if err != nil { t.Fatalf("BuildIndexKey: %v", err) } if err := tbl.DeleteRow("ts_tick", key); err != nil { t.Fatalf("删除 ts=%d: %v", ts, err) } } if err := db.Commit(); err != nil { t.Fatalf("commit: %v", err) } if c := db.Comment(); c != before { t.Fatalf("时序表建/插/删后 Comment=%q, 想要保持 %q", c, before) } }