From 9f0686f35a58e9a795b8dec0a500073e95fdfa51 Mon Sep 17 00:00:00 2001 From: charles Date: Thu, 26 Sep 2024 13:34:11 +0800 Subject: [PATCH] add CI test case for ts-5111 by charles --- tests/army/cluster/test_drop_table_by_uid.py | 368 +++++++++++++++++++ tests/parallel_test/cases.task | 1 + 2 files changed, 369 insertions(+) create mode 100644 tests/army/cluster/test_drop_table_by_uid.py diff --git a/tests/army/cluster/test_drop_table_by_uid.py b/tests/army/cluster/test_drop_table_by_uid.py new file mode 100644 index 0000000000..f09006b37b --- /dev/null +++ b/tests/army/cluster/test_drop_table_by_uid.py @@ -0,0 +1,368 @@ +import time +import random +import taos +from enum import Enum + +from frame.log import * +from frame.cases import * +from frame.sql import * +from frame.caseBase import * +from frame import * +from frame.srvCtl import * + + +class TDTestCase(TBase): + """ + Description: This class is used to verify the feature of 'drop table by uid' for task TS-5111 + FS: https://taosdata.feishu.cn/wiki/JgeDwZkH3iTNv2ksVkWcHenKnTf + TS: https://taosdata.feishu.cn/wiki/DX3FwopwGiXCeRkBNXFcj0MBnnb + create: + 2024-09-23 created by Charles + update: + None + """ + + class TableType(Enum): + STABLE = 0 + CHILD_TABLE = 1 + REGULAR_TABLE = 2 + + def init(self, conn, logSql, replicaVar=1): + """Initialize the TDengine cluster environment + """ + super(TDTestCase, self).init(conn, logSql, replicaVar, db="db") + tdSql.init(conn.cursor(), logSql) + + def get_uid_by_db_table_name(self, db_name, table_name, table_type=TableType.STABLE): + """Get table uid with db name and table name from system table + :param db_name: database name + :param table_name: table name + :param table_type: table type, default is stable + :return: table uid + """ + if table_type == self.TableType.STABLE: + tdSql.query(f"select * from information_schema.ins_stables where db_name='{db_name}' and stable_name like '%{table_name}%';") + elif table_type == self.TableType.CHILD_TABLE: + tdSql.query(f"select * from information_schema.ins_tables where db_name='{db_name}' and table_name like '%{table_name}%' and stable_name is not null;") + else: + tdSql.query(f"select * from information_schema.ins_tables where db_name='{db_name}' and table_name like '%{table_name}%' and stable_name is null;") + # check whether the table uid is empty + if len(tdSql.res) == 0: + tdLog.debug(f"Can't get table uid with db name: {db_name} and table name: {table_name}") + return None + # get table uid list + if table_type == self.TableType.STABLE: + return [item[10] for item in tdSql.res] + else: + return [item[5] for item in tdSql.res] + + def get_uid_by_db_name(self, db_name, table_type=TableType.STABLE): + """Get table uid with db name and table type from system table + :param db_name: database name + :param table_type: table type, default is stable + :return: table uid list + """ + if table_type == self.TableType.STABLE: + tdSql.query(f"select * from information_schema.ins_stables where db_name='{db_name}';") + elif table_type == self.TableType.CHILD_TABLE: + tdSql.query(f"select * from information_schema.ins_tables where db_name='{db_name}' and stable_name is not null;") + else: + tdSql.query(f"select * from information_schema.ins_tables where db_name='{db_name}' and stable_name is null;") + # check whether the table uid is empty + if len(tdSql.res) == 0: + tdLog.debug(f"Can't get table uid with db name: {db_name}") + return None + # get table uid list + if table_type == self.TableType.STABLE: + return [item[10] for item in tdSql.res] + else: + return [item[5] for item in tdSql.res] + + def drop_table_by_uid(self, uid_list, table_type=TableType.STABLE, exist_ops=False): + """Drop the specified tables by uid list + :db_name: database name + :param uid_list: table uid list to be dropped + :param exist_ops: whether to use exist option, default is False + :return: None + """ + # check whether the uid list is empty + if len(uid_list) == 0: + return + # drop table by uid + if exist_ops and table_type == self.TableType.STABLE: + for uid in uid_list: + tdSql.execute(f"drop stable with if exists `{uid}`;") + else: + uids = ','.join(["`" + str(item) + "`" for item in uid_list]) + tdSql.execute(f"drop table with {uids};") + + def test_drop_single_table_by_uid(self): + """Verify the feature of dropping a single stable/child table/regular table by uid with root user + """ + db_name = "test_drop_single_table_by_uid" + tdLog.info("Start test case: test_drop_single_table_by_uid") + # data for case test_drop_single_table_by_uid + tdLog.info("Prepare data for test case test_drop_single_table_by_uid") + tdSql.execute(f"create database {db_name};") + tdSql.execute(f"use {db_name};") + # table with normal characters + tdSql.execute("create stable st1 (ts timestamp, c1 int) tags (t1 int);") + tdSql.execute("create table ct1_1 using st1 tags(1);") + tdSql.execute("create table t1 (ts timestamp, c1 int, c2 float);") + tdLog.info("Finish preparing data for test case test_drop_single_table_by_uid of normal characters") + # get table uid + uid_st1 = self.get_uid_by_db_table_name(db_name, "st1") + tdLog.debug(f"uid_st1: {uid_st1}") + uid_ct1_1 = self.get_uid_by_db_table_name(db_name, "ct1_1", self.TableType.CHILD_TABLE) + tdLog.debug(f"uid_ct1_1: {uid_ct1_1}") + uid_t1 = self.get_uid_by_db_table_name(db_name, "t1", self.TableType.REGULAR_TABLE) + tdLog.debug(f"uid_t1: {uid_t1}") + # drop table by uid + self.drop_table_by_uid(uid_t1, self.TableType.REGULAR_TABLE) + self.drop_table_by_uid(uid_ct1_1, self.TableType.CHILD_TABLE) + self.drop_table_by_uid(uid_st1, self.TableType.STABLE, True) + + # table with special characters + tdSql.execute("create stable `st2\u00bf\u200bfnn1` (ts timestamp, c1 int) tags (t1 int);") + tdSql.execute("create table `ct2_1\u00cf\u00ff` using `st2\u00bf\u200bfnn1` tags(1);") + tdSql.execute("create table `t2\u00ef\u00fa` (ts timestamp, c1 int, c2 float);") + tdLog.info("Finish preparing data for test case test_drop_single_table_by_uid of special characters") + # get table uid + uid_st2 = self.get_uid_by_db_table_name(db_name, "st2") + tdLog.debug(f"uid_st2: {uid_st2}") + uid_ct2_1 = self.get_uid_by_db_table_name(db_name, "ct2_1", self.TableType.CHILD_TABLE) + tdLog.debug(f"uid_ct2_1: {uid_ct2_1}") + uid_t2 = self.get_uid_by_db_table_name(db_name, "t2", self.TableType.REGULAR_TABLE) + tdLog.debug(f"uid_t2: {uid_t2}") + # drop table by uid + self.drop_table_by_uid(uid_t2, self.TableType.REGULAR_TABLE) + self.drop_table_by_uid(uid_ct2_1, self.TableType.CHILD_TABLE) + self.drop_table_by_uid(uid_st2, self.TableType.STABLE, True) + tdSql.execute(f"drop database {db_name};") + tdLog.info("Finish test case: test_drop_single_table_by_uid") + + def test_drop_multiple_tables_by_uid(self): + """Verify the feature of dropping multiple tables by uid with root user + """ + db_name = "test_drop_multiple_tables_by_uid" + table_number = 100 + tdLog.info("Start test case: test_drop_multiple_tables_by_uid") + # data for case test_drop_multiple_tables_by_uid + tdLog.info("Prepare data for test case test_drop_multiple_tables_by_uid") + tdSql.execute(f"create database {db_name};") + tdSql.execute(f"use {db_name};") + # table with normal characters + for i in range(table_number): + tdSql.execute(f"create stable st{i} (ts timestamp, c1 int) tags (t1 int);") + tdSql.execute(f"create table ct{i}_{i} using st{i} tags({i+1});") + tdSql.execute(f"create table t{i} (ts timestamp, c1 int, c2 float);") + tdLog.info("Finish preparing data for test case test_drop_multiple_tables_by_uid of normal characters") + # get table uid + uid_st = self.get_uid_by_db_table_name(db_name, "st") + # tdLog.debug(f"Get multiple stable uid list: {uid_st}") + uid_ct = self.get_uid_by_db_table_name(db_name, "ct", self.TableType.CHILD_TABLE) + # tdLog.debug(f"Get multiple child table uid list: {uid_ct}") + uid_t = self.get_uid_by_db_table_name(db_name, "t", self.TableType.REGULAR_TABLE) + # tdLog.debug(f"Get multiple regular table uid list: {uid_t}") + # drop table by uid + self.drop_table_by_uid(uid_t, self.TableType.REGULAR_TABLE) + self.drop_table_by_uid(uid_ct, self.TableType.CHILD_TABLE) + self.drop_table_by_uid(uid_st, self.TableType.STABLE, True) + + # table with special characters + for i in range(table_number): + tdSql.execute(f"create stable `st{i}\u00bf\u200bfnn1` (ts timestamp, c1 int) tags (t1 int);") + tdSql.execute(f"create table `ct{i}_{i}\u00cf\u00ff` using `st{i}\u00bf\u200bfnn1` tags(1);") + tdSql.execute(f"create table `t{i}\u00ef\u00fa` (ts timestamp, c1 int, c2 float);") + # get table uid + uid_st = self.get_uid_by_db_table_name(db_name, "st") + # tdLog.debug(f"Get multiple stable uid list: {uid_st}") + uid_ct = self.get_uid_by_db_table_name(db_name, "ct", self.TableType.CHILD_TABLE) + # tdLog.debug(f"Get multiple child table uid list: {uid_ct}") + uid_t = self.get_uid_by_db_table_name(db_name, "t", self.TableType.REGULAR_TABLE) + # tdLog.debug(f"Get multiple regular table uid list: {uid_t}") + # drop table by uid + self.drop_table_by_uid(uid_t, self.TableType.REGULAR_TABLE) + self.drop_table_by_uid(uid_ct, self.TableType.CHILD_TABLE) + self.drop_table_by_uid(uid_st, self.TableType.STABLE, True) + tdSql.execute(f"drop database {db_name};") + tdLog.info("Finish test case: test_drop_multiple_tables_by_uid") + + def test_uid_as_table_name(self): + """Verify using uid as table name, drop table with uid doesn't affect other tables + """ + db_name = "test_uid_as_table_name" + tdLog.info("Start test case: test_uid_as_table_name") + # data for case test_uid_as_table_name + tdLog.info("Prepare data for test case test_uid_as_table_name") + tdSql.execute(f"create database {db_name};") + tdSql.execute(f"use {db_name};") + # super table + tdSql.execute(f"create stable `st1\u00bf\u200bfnn1` (ts timestamp, c1 int) tags (t1 int);") + uid_st = self.get_uid_by_db_table_name(db_name, "st") + tdSql.execute(f"create stable `{uid_st[0]}` (ts timestamp, c1 int) tags (t1 int);") + self.drop_table_by_uid(uid_st, self.TableType.STABLE, True) + uid_st = self.get_uid_by_db_table_name(db_name, str(uid_st[0])) + assert uid_st is not None + tdLog.info(f"Drop stable with special characters with uid {uid_st[0]}, stable named as {uid_st[0]} doesn't be affected") + # child table + tdSql.execute(f"create stable `st2\u00bf\u200bfnn1` (ts timestamp, c1 int) tags (t1 int);") + tdSql.execute(f"create table `ct2_1\u00cf\u00ff` using `st2\u00bf\u200bfnn1` tags(1);") + uid_ct = self.get_uid_by_db_table_name(db_name, "ct", self.TableType.CHILD_TABLE) + tdSql.execute(f"create table `{uid_ct[0]}` using `st2\u00bf\u200bfnn1` tags(2);") + self.drop_table_by_uid(uid_ct, self.TableType.CHILD_TABLE) + uid_ct = self.get_uid_by_db_table_name(db_name, str(uid_ct[0]), self.TableType.CHILD_TABLE) + assert uid_ct is not None + tdLog.info(f"Drop child table with special characters with uid {uid_ct[0]}, child table named as {uid_ct[0]} doesn't be affected") + # regular table + tdSql.execute(f"create table `t2\u00bf\u200bfnn1` (ts timestamp, c1 int);") + uid_t = self.get_uid_by_db_table_name(db_name, "t2", self.TableType.REGULAR_TABLE) + tdSql.execute(f"create table `{uid_t[0]}` (ts timestamp, c1 int);") + self.drop_table_by_uid(uid_t, self.TableType.REGULAR_TABLE) + uid_t = self.get_uid_by_db_table_name(db_name, str(uid_t[0]), self.TableType.REGULAR_TABLE) + assert uid_t is not None + tdLog.info(f"Drop regular table with special characters with uid {uid_t[0]}, regular table named as {uid_t[0]} doesn't be affected") + tdSql.execute(f"drop database {db_name};") + tdLog.info("Finish test case: test_uid_as_table_name") + + def test_abnormal_non_exist_uid(self): + """Verify dropping table with non-exist uid + """ + db_name = "test_abnormal_non_exist_uid" + tdLog.info("Start test case: test_abnormal_non_exist_uid") + # data for case test_abnormal_non_exist_uid + tdLog.info("Prepare data for test case test_abnormal_non_exist_uid") + tdSql.execute(f"create database {db_name};") + tdSql.execute(f"use {db_name};") + # drop table with non-exist uid + tdSql.error(f"drop stable with if exists `1234567890`;", expectErrInfo="STable not exist:") + tdSql.error(f"drop table with `1234567890`;", expectErrInfo="Table does not exist:") + tdSql.execute(f"drop database {db_name};") + tdLog.info("Finish test case: test_abnormal_non_exist_uid") + + def test_abnormal_incorrect_table_type(self): + """Verify dropping table with incorrect sql, like drop stable sql with table or child table uid + """ + try: + db_name = "test_abnormal_incorrect_table_type" + tdLog.info("Start test case: test_abnormal_incorrect_table_type") + # data for case test_abnormal_incorrect_table_type + tdLog.info("Prepare data for test case test_abnormal_incorrect_table_type") + tdSql.execute(f"create database {db_name};") + tdSql.execute(f"use {db_name};") + tdSql.execute("create stable `st3\u00bf\u200bfnn1` (ts timestamp, c1 int) tags (t1 int);") + tdSql.execute("create table `ct3_1\u00cf\u00ff` using `st3\u00bf\u200bfnn1` tags(1);") + tdSql.execute("create table `t3\u00ef\u00fa` (ts timestamp, c1 int, c2 float);") + tdLog.info("Finish preparing data for test case test_abnormal_incorrect_table_type of special characters") + # get table uid + uid_st = self.get_uid_by_db_table_name(db_name, "st") + uid_ct = self.get_uid_by_db_table_name(db_name, "ct", self.TableType.CHILD_TABLE) + uid_t = self.get_uid_by_db_table_name(db_name, "t", self.TableType.REGULAR_TABLE) + # drop table with incorrect sql + tdSql.error(f"drop stable with `{uid_ct[0]}`;", expectErrInfo="STable not exist") + tdSql.error(f"drop stable with `{uid_t[0]}`;", expectErrInfo="STable not exist") + tdLog.info("Finish test case: test_abnormal_incorrect_table_type") + except Exception as e: + tdLog.exit("Failed to run test case test_abnormal_incorrect_table_type with msg: %s" % str(e)) + finally: + tdSql.execute(f"drop database {db_name};") + + def test_abnormal_mixed_uid(self): + """Verify dropping table with mixed uid + """ + db_name = "test_abnormal_mixed_uid" + tdLog.info("Start test case: test_abnormal_mixed_uid") + # data for case test_abnormal_mixed_uidF + tdLog.info("Prepare data for test case test_abnormal_mixed_uid") + tdSql.execute(f"create database {db_name};") + tdSql.execute(f"use {db_name};") + tdSql.execute("create stable `st3\u00bf\u200bfnn1` (ts timestamp, c1 int) tags (t1 int);") + tdSql.execute("create table `ct3_1\u00cf\u00ff` using `st3\u00bf\u200bfnn1` tags(1);") + tdSql.execute("create table `t3\u00ef\u00fa` (ts timestamp, c1 int, c2 float);") + tdLog.info("Finish preparing data for test case test_abnormal_mixed_uid of special characters") + # get table uid + uid_st = self.get_uid_by_db_table_name(db_name, "st") + uid_ct = self.get_uid_by_db_table_name(db_name, "ct", self.TableType.CHILD_TABLE) + uid_t = self.get_uid_by_db_table_name(db_name, "t", self.TableType.REGULAR_TABLE) + # drop table with incorrect sql + tdSql.error(f"drop stable with `{uid_st[0]}`,`{uid_ct[0]}`;", expectErrInfo="syntax error") + tdSql.error(f"drop table with `{uid_st[0]}`,`{uid_ct[0]}`,`{uid_t[0]}`;", expectErrInfo="Cannot drop super table in batch") + tdSql.execute(f"drop database {db_name};") + tdLog.info("Finish test case: test_abnormal_mixed_uid") + + def test_abnormal_system_tables(self): + """Verify dropping system tables + """ + try: + uid_list = self.get_uid_by_db_name("information_schema", self.TableType.REGULAR_TABLE) + uid = random.choice(uid_list) + assert uid is None + except Exception as e: + tdLog.exit("Failed to run test case test_abnormal_system_tables with msg: %s" % str(e)) + + def test_abnormal_drop_table_with_non_root_user(self): + """Verify dropping table with non-root user + """ + try: + # create new user and grant create database priviledge + tdSql.execute("create user test pass 'test';") + tdSql.execute("alter user test createdb 1;") + conn = taos.connect(user="test", password="test") + cursor = conn.cursor() + # create database and tables with new user + tdLog.info("Prepare data for test case test_abnormal_drop_table_with_non_root_user") + db_name = "test_abnormal_drop_table_with_non_root_user" + cursor.execute(f"create database {db_name};") + cursor.execute(f"use {db_name};") + time.sleep(3) + cursor.execute("create stable `st4\u00bf\u200bfnn1` (ts timestamp, c1 int) tags (t1 int);") + cursor.execute("create table `ct4_1\u00cf\u00ff` using `st4\u00bf\u200bfnn1` tags(1);") + cursor.execute("create table `t4\u00ef\u00fa` (ts timestamp, c1 int, c2 float);") + tdLog.info("Finish preparing data for test case test_abnormal_drop_table_with_non_root_user of special characters") + # get table uid + uid_st = self.get_uid_by_db_table_name(db_name, "st") + uid_ct = self.get_uid_by_db_table_name(db_name, "ct", self.TableType.CHILD_TABLE) + uid_t = self.get_uid_by_db_table_name(db_name, "t", self.TableType.REGULAR_TABLE) + # drop stable with sql by non-root user + try: + cursor.execute(f"drop stable with `{uid_st[0]}`;") + except Exception as e: + assert "Permission denied or target object not exist" in str(e) + tdLog.info("Drop stable with non-root user failed as expected") + # drop child table with sql by non-root user + try: + cursor.execute(f"drop table with `{uid_ct[0]}`;") + except Exception as e: + assert "Permission denied or target object not exist" in str(e) + tdLog.info("Drop child table with non-root user failed as expected") + # drop regular table with sql by non-root user + try: + cursor.execute(f"drop table with `{uid_t[0]}`;") + except Exception as e: + assert "Permission denied or target object not exist" in str(e) + tdLog.info("Drop regular table with non-root user failed as expected") + tdLog.info("Finish test case: test_abnormal_drop_table_with_non_root_user") + except Exception as e: + tdLog.exit("Failed to run test case test_abnormal_drop_table_with_non_root_user with msg: %s" % str(e)) + finally: + tdSql.execute(f"drop database {db_name};") + tdSql.execute("drop user test;") + + def run(self): + # normal cases + self.test_drop_single_table_by_uid() + self.test_drop_multiple_tables_by_uid() + self.test_uid_as_table_name() + # abnormal cases + self.test_abnormal_non_exist_uid() + self.test_abnormal_incorrect_table_type() + self.test_abnormal_mixed_uid() + self.test_abnormal_system_tables() + self.test_abnormal_drop_table_with_non_root_user() + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 602ac9ad66..9921588a77 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -23,6 +23,7 @@ ,,y,army,./pytest.sh python3 ./test.py -f insert/test_column_tag_boundary.py ,,y,army,./pytest.sh python3 ./test.py -f query/fill/fill_desc.py -N 3 -L 3 -D 2 ,,y,army,./pytest.sh python3 ./test.py -f query/fill/fill_null.py +,,y,army,./pytest.sh python3 ./test.py -f cluster/test_drop_table_by_uid.py -N 3 ,,y,army,./pytest.sh python3 ./test.py -f cluster/incSnapshot.py -N 3 ,,y,army,./pytest.sh python3 ./test.py -f cluster/clusterBasic.py -N 5 ,,y,army,./pytest.sh python3 ./test.py -f query/query_basic.py -N 3