@@ -34,18 +34,9 @@ def setup_cls(cls):
3434 tdLog .debug ("start to execute %s" % __file__ )
3535 cls .setsql = TDSetSql ()
3636
37- def s0_five_dnode_one_mnode (self ):
37+ def s0_prepare_test_data (self ):
38+ tdLog .info ("======== s0_prepare_test_data: " )
3839 tdSql .query ("select * from information_schema.ins_dnodes;" )
39- tdSql .checkData (0 ,1 ,'%s:6030' % self .host )
40- tdSql .checkData (4 ,1 ,'%s:6430' % self .host )
41- tdSql .checkData (0 ,4 ,'ready' )
42- tdSql .checkData (4 ,4 ,'ready' )
43- tdSql .query ("select * from information_schema.ins_mnodes;" )
44- tdSql .checkData (0 ,1 ,'%s:6030' % self .host )
45- tdSql .checkData (0 ,2 ,'leader' )
46- tdSql .checkData (0 ,3 ,'ready' )
47- tdSql .error ("create mnode on dnode 1;" )
48- tdSql .error ("drop mnode on dnode 1;" )
4940 tdSql .execute ("create database if not exists audit keep 36500d" );
5041 tdSql .execute ("use audit" );
5142 tdSql .execute ("create table operations(ts timestamp, c0 int primary key,c1 bigint,c2 int,c3 float,c4 double) tags(t0 bigint unsigned)" );
@@ -65,12 +56,7 @@ def s0_five_dnode_one_mnode(self):
6556 tdLog .info (f"insert data { r } into stb0" )
6657 tdSql .query (f"insert into db.ctb0 values(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f)(now + %ds, %d, %d, %d, %f, %f) " % (r , r * 2 , r * 4 , r * 3 , float (r )/ 39 , float (r )/ 23 ,r + 1 , (r + 1 )* 2 , (r + 1 )* 4 , (r + 1 )* 3 , float (r )/ 139 , float (r )/ 123 ,r + 2 , (r + 2 )* 2 , (r + 2 )* 4 , (r + 2 )* 3 , float (r )/ 239 , float (r )/ 223 ,r + 3 , (r + 3 )* 2 , (r + 3 )* 4 , (r + 3 )* 3 , float (r )/ 339 , float (r )/ 323 ,r + 4 , (r + 4 )* 2 , (r + 4 )* 4 , (r + 4 )* 3 , float (r )/ 439 , float (r )/ 423 ,r + 5 , r + 5 * 2 , r + 5 * 4 , r + 5 * 3 , float (r )/ 539 , float (r )/ 523 ,r + 6 , r + 6 * 2 , r + 6 * 4 , r + 6 * 3 , float (r )/ 639 , float (r )/ 623 ,r + 7 , r + 7 * 2 , r + 7 * 4 , r + 7 * 3 , float (r )/ 739 , float (r )/ 723 ,r + 8 , r + 8 * 2 , r + 8 * 4 , r + 8 * 3 , float (r )/ 839 , float (r )/ 823 ,r + 9 , r + 9 * 2 , r + 9 * 4 , r * 3 , float (r )/ 939 , float (r )/ 923 ))
6758 tdSql .execute ("flush database db" )
68-
69- def getConnection (self , dnode ):
70- host = dnode .cfgDict ["fqdn" ]
71- port = dnode .cfgDict ["serverPort" ]
72- config_dir = dnode .cfgDir
73- return taos .connect (host = host , port = int (port ), config = config_dir )
59+ tdLog .info ("prepare test data done" )
7460
7561 def getShowGrantsTimeSeries (self , maxRetry = 10 ):
7662 for nRetry in range (maxRetry ):
@@ -79,26 +65,30 @@ def getShowGrantsTimeSeries(self, maxRetry=10):
7965 tdSql .query ("show grants full" )
8066 full_timeseries = tdSql .queryResult [1 ][3 ]
8167 if timeseries == full_timeseries :
68+ tdLog .info (f"timeseries: { timeseries } , == full_timeseries: { full_timeseries } , retried: { nRetry } " )
8269 return int (timeseries .split ('/' )[0 ])
8370 else :
8471 tdLog .info (f"timeseries: { timeseries } , != full_timeseries: { full_timeseries } , retry: { nRetry } " )
8572 time .sleep (1 )
8673 raise Exception ("Timeseries not equal within {maxRetry} seconds" )
8774
88- def getTablesTimeSeries (self ):
75+ def getTablesTimeSeries (self , ):
8976 tdSql .query (f"select cast(sum(columns-1) as int) as tss from information_schema.ins_tables where db_name not in ('information_schema', 'performance_schema', 'audit') and type not like '%VIRTUAL%'" )
9077 return int (tdSql .queryResult [0 ][0 ])
9178
92- def checkGrantsTimeSeries (self , prompt = "" , nExpectedTimeSeries = 0 , maxRetry = 10 ):
79+ def checkGrantsTimeSeries (self , prompt = "" , nExpectedTimeSeries = 0 , strictMode = False , maxRetry = 10 ):
9380 for nRetry in range (maxRetry ):
9481 tss_grant = self .getShowGrantsTimeSeries ()
9582 if tss_grant == nExpectedTimeSeries :
83+ if not strictMode :
84+ return
9685 tss_table = self .getTablesTimeSeries ()
9786 if tss_grant == tss_table :
9887 tdLog .info (f"{ prompt } : tss_grant: { tss_grant } == tss_table: { tss_table } " )
9988 return
10089 else :
10190 raise Exception (f"{ prompt } : tss_grant: { tss_grant } != tss_table: { tss_table } " )
91+ tdLog .info (f"{ prompt } : tss_grant: { tss_grant } != nExpectedTimeSeries: { nExpectedTimeSeries } , retry: { nRetry } " )
10292 time .sleep (1 )
10393 raise Exception (f"{ prompt } : tss_grant: { tss_grant } != nExpectedTimeSeries: { nExpectedTimeSeries } " )
10494
@@ -107,15 +97,8 @@ def clearEnv(self):
10797 os .remove (self .infoPath )
10898
10999 def s1_check_timeseries (self ):
110- # check cluster alive
111- tdLog .printNoPrefix ("======== test cluster alive: " )
112- tdSql .checkDataLoop (0 , 0 , 1 , "show cluster alive;" , 20 , 0.5 )
113-
114- tdSql .query ("show db.alive;" )
115- tdSql .checkData (0 , 0 , 1 )
116-
117- # check timeseries
118- tss_grant = 9
100+ tdLog .info ("======== test timeseries: " )
101+ tss_grant = 11
119102 for i in range (0 , 3 ):
120103 tdLog .printNoPrefix (f"======== test timeseries: loop{ i } " )
121104 self .checkGrantsTimeSeries ("initial check" , tss_grant )
@@ -172,6 +155,7 @@ def s1_check_timeseries(self):
172155 self .checkGrantsTimeSeries ("drop database and check" , tss_grant )
173156
174157 def genClusterInfo (self , check = False ):
158+ tdLog .info ("======== genClusterInfo: " )
175159 self .infoPath = os .path .join (self .workPath , ".clusterInfo" )
176160 infoFile = open (self .infoPath , "w" )
177161 try :
@@ -271,15 +255,15 @@ def s4_ts6191_check_dual_replica(self):
271255
272256 def s5_check_timeseries_exclude_systable (self ):
273257 """
274- 测试计算测点时排除系统表的功能
258+ Test the functionality of excluding system tables when calculating timeseries count(6672169603).
275259
276- 排除的系统表为超级表:
277- 1. log 库中的超级表 (tkLogStb)
278- 2. audit 库中的超级表 (tkAuditStb), audit 库的判断条件:
279- - 数据库名为 audit
280- - 或者建库语句中指明 is_audit 1
260+ The excluded system tables are supertables:
261+ 1. Supertables in the ' log' database (tkLogStb)
262+ 2. Supertables in the ' audit' database (tkAuditStb), where audit database is identified by:
263+ - Database name is ' audit'
264+ - Or the database is created with ' is_audit 1' option
281265 """
282- # log 库的系统表超级表列表
266+ # List of system supertables in the ' log' database
283267 tkLogStb = [
284268 "cluster_info" , "data_dir" , "dnodes_info" , "d_info" , "grants_info" ,
285269 "keeper_monitor" , "logs" , "log_dir" , "log_summary" , "m_info" ,
@@ -298,102 +282,103 @@ def s5_check_timeseries_exclude_systable(self):
298282 "taosx_task_mongodb" , "taosx_task_sparkplugb" , "taosx_task_orc" , "taosx_task_pulsar" , "taosx_task_pspace"
299283 ]
300284
301- # audit 库的系统表超级表列表
285+ # List of system supertables in the ' audit' database
302286 tkAuditStb = ["operations" ]
303287
304288 tdLog .printNoPrefix ("======== test timeseries exclude systable: " )
305289 try :
306- # 获取当前的 timeseries 数量作为基准
307- tss_grant_base = self . getShowGrantsTimeSeries ()
308- tdLog . info ( f"Base timeseries count: { tss_grant_base } " )
290+ # Get the current timeseries count as baseline
291+ tss_grant_base = 11 # table + stream result table
292+ self . checkGrantsTimeSeries ( "initial grant check" , tss_grant_base )
309293
310- # ========== 测试1: 验证 audit 库中的 operations 表不计入 timeseries ==========
294+ # ========== Test1: Verify operations table in audit db is excluded from timeseries ==========
311295 tdLog .printNoPrefix ("======== test1: audit db operations table should be excluded" )
312- # audit 库已在 s0_five_dnode_one_mnode 中创建,包含 operations 超级表
313- # 验证 audit 库中的 operations 子表不计入 timeseries
296+ # audit db was created in s0_prepare_test_data with operations supertable
297+ # Verify that operations child tables in audit db are not counted in timeseries
314298 tdSql .execute ("use audit" )
315299 tdSql .execute ("insert into t_operations_abc values(now, 1, 100, 10, 1.0, 2.0)" )
316300 tdSql .execute ("create table t_operations_def using operations tags(2)" )
317301 tdSql .execute ("insert into t_operations_def values(now, 2, 200, 20, 2.0, 3.0)" )
318302
319- # 验证 timeseries 数量不变( audit 库的 operations 表应被排除)
303+ # Verify timeseries count unchanged ( audit db operations table should be excluded)
320304 self .checkGrantsTimeSeries ("audit db operations should be excluded" , tss_grant_base )
321305 tdLog .info ("test1 passed: audit db operations table excluded from timeseries count" )
322306
323- # ========== 测试2: 验证 is_audit 标记的库中的 operations 表不计入 timeseries ==========
307+ # ========== Test2: Verify operations table in is_audit db is excluded from timeseries ==========
324308 tdLog .printNoPrefix ("======== test2: is_audit db operations table should be excluded" )
325309 tdSql .execute ("drop database if exists audit_test" )
310+ tdSql .error ("create database `log` is_audit 1 wal_level 2 ENCRYPT_ALGORITHM 'SM4-CBC' keep 36500d" , expectErrInfo = "Invalid database name" , fullMatched = False )
326311 tdSql .execute ("create database audit_test is_audit 1 wal_level 2 ENCRYPT_ALGORITHM 'SM4-CBC' keep 36500d" )
327312 tdSql .execute ("use audit_test" )
328- # 在 is_audit 库中创建 operations 超级表和子表
329- tdSql .execute ("create table operations(ts timestamp, c0 int primary key, c1 bigint, c2 int, c3 float, c4 double) tags(t0 bigint unsigned)" )
330- tdSql .execute ("create table t_ops_1 using operations tags(1)" )
331- tdSql .execute ("insert into t_ops_1 values(now, 1, 100, 10, 1.0, 2.0)" )
332- tdSql .execute ("create table t_ops_2 using operations tags(2)" )
333- tdSql .execute ("insert into t_ops_2 values(now, 2, 200, 20, 2.0, 3.0)" )
313+ # Create operations supertable and child tables in is_audit db
314+ tdSql .execute ("create table ` operations` (ts timestamp, c0 int primary key, c1 bigint, c2 int, c3 float, c4 double) tags(t0 bigint unsigned)" )
315+ tdSql .execute ("create table ` t_ops_1` using ` operations` tags(1)" )
316+ tdSql .execute ("insert into ` t_ops_1` values(now, 1, 100, 10, 1.0, 2.0)" )
317+ tdSql .execute ("create table ` t_ops_2` using ` operations` tags(2)" )
318+ tdSql .execute ("insert into ` t_ops_2` values(now, 2, 200, 20, 2.0, 3.0)" )
334319
335- # 验证 timeseries 数量不变( is_audit 库的 operations 表应被排除)
320+ # Verify timeseries count unchanged ( is_audit db operations table should be excluded)
336321 self .checkGrantsTimeSeries ("is_audit db operations should be excluded" , tss_grant_base )
337322 tdLog .info ("test2 passed: is_audit db operations table excluded from timeseries count" )
338323
339- # ========== 测试3: 验证 is_audit 库中的非 operations 表正常计入 timeseries ==========
324+ # ========== Test3: Verify non-operations table in is_audit db is counted in timeseries ==========
340325 tdLog .printNoPrefix ("======== test3: is_audit db non-operations table should be counted" )
341326 tdSql .execute ("use audit_test" )
342- # 在 is_audit 库中创建非 operations 的普通表
327+ # Create non-operations table in is_audit db
343328 tdSql .execute ("create table normal_stb(ts timestamp, c0 int, c1 bigint, c2 int) tags(t0 int)" )
344329 tdSql .execute ("create table t_normal_1 using normal_stb tags(1)" )
345330 tdSql .execute ("insert into t_normal_1 values(now, 1, 100, 10)" )
346331 tss_grant_expected = tss_grant_base + 3 # 3 columns (excluding ts)
347332 self .checkGrantsTimeSeries ("is_audit db non-operations table should be counted" , tss_grant_expected )
348333 tdLog .info ("test3 passed: is_audit db non-operations table counted in timeseries" )
349334
350- # ========== 测试4: 验证普通库中的 operations 表正常计入 timeseries ==========
335+ # ========== Test4: Verify operations table in normal db is counted in timeseries ==========
351336 tdLog .printNoPrefix ("======== test4: normal db operations table should be counted" )
352337 tdSql .execute ("drop database if exists normal_test" )
353338 tdSql .execute ("create database normal_test keep 36500d" )
354339 tdSql .execute ("use normal_test" )
355- # 在普通库中创建同名的 operations 超级表和子表
340+ # Create operations supertable with same name in normal db
356341 tdSql .execute ("create table operations(ts timestamp, c0 int primary key, c1 bigint, c2 int, c3 float, c4 double) tags(t0 bigint unsigned)" )
357342 tdSql .execute ("create table t_ops_normal_1 using operations tags(1)" )
358343 tdSql .execute ("insert into t_ops_normal_1 values(now, 1, 100, 10, 1.0, 2.0)" )
359344 tss_grant_expected += 5 # 5 columns (excluding ts)
360345 self .checkGrantsTimeSeries ("normal db operations table should be counted" , tss_grant_expected )
361346 tdLog .info ("test4 passed: normal db operations table counted in timeseries" )
362347
363- # ========== 测试5: 验证 log 库中的系统表不计入 timeseries ==========
364- tdLog .printNoPrefix ("======== test5: log db system tables should be excluded" )
348+ # ========== Test5: Verify ALL system tables in log db are excluded from timeseries ==========
349+ tdLog .printNoPrefix ("======== test5: log db system tables should be excluded (full coverage) " )
365350 tdSql .execute ("drop database if exists log" )
366351 tdSql .execute ("create database log keep 36500d" )
367352 tdSql .execute ("use log" )
368- # 在 log 库中创建部分系统表超级表和子表
369- test_log_stbs = ["cluster_info" , "dnodes_info" , "grants_info" , "logs" ]
370- for stb_name in test_log_stbs :
371- tdSql .execute (f"create table { stb_name } (ts timestamp, c0 int, c1 bigint, c2 int, c3 float, c4 double) tags(t0 bigint unsigned)" )
372- tdSql .execute (f"create table t_{ stb_name } _1 using { stb_name } tags(1)" )
373- tdSql .execute (f"insert into t_{ stb_name } _1 values(now, 1, 100, 10, 1.0, 2.0)" )
353+ # Create ALL system supertables and child tables in log db (full coverage test)
354+ for stb_name in tkLogStb :
355+ tdSql .execute (f"create table `{ stb_name } `(ts timestamp, c0 int, c1 bigint, c2 int, c3 float, c4 double) tags(t0 bigint unsigned)" )
356+ tdSql .execute (f"create table `t_{ stb_name } _1` using `{ stb_name } ` tags(1)" )
357+ tdSql .execute (f"insert into `t_{ stb_name } _1` values(now, 1, 100, 10, 1.0, 2.0)" )
374358
375- # 验证 timeseries 数量不变( log 库的系统表应被排除)
359+ # Verify timeseries count unchanged (all log db system tables should be excluded)
376360 self .checkGrantsTimeSeries ("log db system tables should be excluded" , tss_grant_expected )
377- tdLog .info ("test5 passed: log db system tables excluded from timeseries count" )
361+ tdLog .info (f "test5 passed: all { len ( tkLogStb ) } log db system tables excluded from timeseries count" )
378362
379- # ========== 测试6: 验证 log 库中的非系统表正常计入 timeseries ==========
363+ # ========== Test6: Verify non-system table in log db is counted in timeseries ==========
380364 tdLog .printNoPrefix ("======== test6: log db non-system table should be counted" )
381365 tdSql .execute ("use log" )
382- # 在 log 库中创建非系统表的普通表
383- tdSql .execute ("create table user_defined_stb(ts timestamp, c0 int, c1 bigint, c2 int) tags(t0 int)" )
384- tdSql .execute ("create table t_user_1 using user_defined_stb tags(1)" )
385- tdSql .execute ("insert into t_user_1 values(now, 1, 100, 10)" )
366+ # Create non-system table in log db
367+ tdSql .execute ("create table ` user_defined_stb` (ts timestamp, c0 int, c1 bigint, c2 int) tags(t0 int)" )
368+ tdSql .execute ("create table ` t_user_1` using ` user_defined_stb` tags(1)" )
369+ tdSql .execute ("insert into ` t_user_1` values(now, 1, 100, 10)" )
386370 tss_grant_expected += 3 # 3 columns (excluding ts)
387371 self .checkGrantsTimeSeries ("log db non-system table should be counted" , tss_grant_expected )
388372 tdLog .info ("test6 passed: log db non-system table counted in timeseries" )
389373
390- # ========== 清理测试数据 ==========
374+ # ========== Cleanup test data ==========
391375 tdLog .printNoPrefix ("======== cleanup test databases" )
376+ tdSql .execute ("alter database `audit_test` allow_drop 1" )
392377 tdSql .execute ("drop database if exists audit_test" )
393378 tdSql .execute ("drop database if exists normal_test" )
394379 tdSql .execute ("drop database if exists log" )
395380
396- # 验证清理后 timeseries 恢复到基准值
381+ # Verify timeseries restored to base count after cleanup
397382 self .checkGrantsTimeSeries ("cleanup and verify base timeseries" , tss_grant_base )
398383 tdLog .info ("cleanup completed, timeseries restored to base count" )
399384
@@ -404,41 +389,40 @@ def s5_check_timeseries_exclude_systable(self):
404389 raise Exception (repr (e ))
405390
406391 def test_grant (self ):
407- """summary: xxx
392+ """
393+ summary: Verify grant-related timeseries statistics and system table exclusion logic
408394
409- description: xxx
395+ description:
396+ This test case mainly verifies the timeseries statistics function related to TDengine grant, focusing on the following aspects:
397+ 1. Whether timeseries statistics are accurate for normal tables, supertables, and virtual tables.
398+ 2. Specific supertables (such as operations, tkLogStb) in system databases like audit and log should be excluded from timeseries statistics.
399+ 3. Exclusion logic for operations tables in databases marked with is_audit.
400+ 4. Consistency of statistics for grant-related commands (show grants, show grants full).
401+ 5. The impact of adding, deleting, and modifying various tables on timeseries statistics.
410402
411- Since: xxx
403+ Since: 2026-03-13
412404
413- Labels: xxx
405+ Labels: grant, timeseries, system-table, audit, log, regression
414406
415- Jira: xxx
407+ Jira: 6672169603
416408
417409 Catalog:
418- - xxx:xxx
410+ - Feature: Grant and timeseries statistics
411+ - Scenario: System table exclusion, grant statistics consistency
419412
420413 History:
421- - xxx
422- - xxx
414+ - 2026-03-13: Initial migration, covering main grant and timeseries statistics process from Cary Xu.
415+ - 2026-03-13: Added system table exclusion and is_audit database scenarios from Cary Xu.
423416 """
424- # print(self.master_dnode.cfgDict)
425417 # keep the order of following steps
426-
427- # self.TDDnodes = None
428- # self.deploy_cluster(5)
429- # self.master_dnode = tdDnodes.dnodes[0]
430- # self.host=self.master_dnode.cfgDict["fqdn"]
431- # conn1 = taos.connect(self.master_dnode.cfgDict["fqdn"] , config=self.master_dnode.cfgDir)
432- # tdSql.init(conn1.cursor(), True)
433418 self .workPath = os .path .join (tdCom .getBuildPath (), "build" , "bin" )
434419 tdLog .info (self .workPath )
435- self .s0_five_dnode_one_mnode ()
436- # self.s1_check_timeseries()
437- # self.s2_check_show_grants_ungranted()
438- # self.s3_check_show_grants_granted()
439- # self.s4_ts6191_check_dual_replica()
420+ self .s0_prepare_test_data ()
421+ self .s1_check_timeseries ()
422+ # self.s2_check_show_grants_ungranted() # migrated later
423+ # self.s3_check_show_grants_granted() # migrated later
424+ # self.s4_ts6191_check_dual_replica() # migrated later
440425 self .s5_check_timeseries_exclude_systable ()
441-
442426 self .clearEnv ()
443427
444428
0 commit comments