TDengine/test/cases/18-StreamProcessing/30-OldPyCases/test_oldcase_string_func.py

149 lines
5.3 KiB
Python

from new_test_framework.utils import tdLog, tdSql, tdStream
import pytest
import time
import random
import string
import re
class TestStringFunctionInStream:
@pytest.mark.parametrize(
"string_func",
[
"char_length(val)",
"concat(val, 'abc')",
"concat_ws('-', val, 'abc')",
"length(val)",
"lower(val)",
"ltrim(val)",
"rtrim(val)",
"substr(val, 1, 3)",
"upper(val)",
],
)
def test_string_function(self, string_func):
"""OldPy: string function
旧用例 tests/system-test/8-stream/scalar_function.py
测试在流计算中使用字符串函数
旧的建流语句:
create stream XXX trigger at_once ignore expired 0 ignore update 0 fill_history 1 into XXX as select ts, char_length(c3) from scalar_tb
新的建流语句:
CREATE STREAM XXX SLIDING(10s) FROM tb INTO XXX AS SELECT ts, char_length(val) as val FROM %%trows;
Catalog:
- Streams:OldPyCases
Since: v3.3.7.0
Labels: common,ci
Jira: https://jira.taosdata.com:18080/browse/TD-36887
History:
- 2025-07-23: Created by zyyang90
"""
# create snode if not exists
snodes = tdSql.getResult("SHOW SNODES;")
if snodes is None or len(snodes) == 0:
tdStream.createSnode()
self.db = "test_string_func_in_stream"
self.stream = "stream_output"
# create database and table
tdSql.executes(
[
f"DROP DATABASE IF EXISTS `{self.db}`;",
f"CREATE DATABASE IF NOT EXISTS `{self.db}`;",
f"USE `{self.db}`;",
"CREATE TABLE tb(ts TIMESTAMP, val VARCHAR(20));",
],
queryTimes=1,
)
# create stream
tdSql.execute(
f"CREATE STREAM {self.stream} SLIDING(10s) FROM tb INTO {self.stream} AS SELECT _tprev_ts AS wstart, _tcurrent_ts AS wend, {string_func} AS val FROM %%trows;",
queryTimes=1,
)
tdStream.checkStreamStatus()
# insert data
ts = (int(time.time()) // 60) * 60 * 1000 # 当前时间取整分钟的时间戳
# 生成随机字符串
val = "".join(random.choices(string.ascii_letters + string.digits, k=10))
if string_func.startswith("ltrim"):
val = f" {val}" # 添加前后空格以测试 ltrim
elif string_func.startswith("rtrim"):
val = f"{val} "
tdSql.execute(f"INSERT INTO tb VALUES({ts}, '{val}');", queryTimes=1)
# 计算 expected value
if string_func.startswith("char_length") or string_func.startswith("length"):
expected = len(val)
elif string_func.startswith("concat_ws"):
# 解析 concat_ws 的参数并组合 expected 字符串
match = re.match(r"concat_ws\(([^,]+),\s*([^,]+),\s*([^)]+)\)", string_func)
if match:
sep = match.group(1).strip("'\"")
str1 = match.group(2).strip("'\"")
str2 = match.group(3).strip("'\"")
if str1 == "val":
str1 = val
elif str2 == "val":
str2 = val
expected = f"{str1}{sep}{str2}"
else:
tdLog.error(f"Invalid concat_ws function: {string_func}")
expected = None
elif string_func.startswith("concat"):
# 解析 concat 的参数并组合 expected 字符串
match = re.match(r"concat\(([^,]+),\s*([^,]+)\)", string_func)
if match:
str1 = match.group(1).strip("'\"")
str2 = match.group(2).strip("'\"")
if str1 == "val":
str1 = val
elif str2 == "val":
str2 = val
expected = f"{str1}{str2}"
else:
tdLog.error(f"Invalid concat function: {string_func}")
expected = None
elif string_func.startswith("lower"):
expected = val.lower()
elif string_func.startswith("upper"):
expected = val.upper()
elif string_func.startswith("ltrim"):
expected = val.lstrip()
elif string_func.startswith("rtrim"):
expected = val.rstrip()
elif string_func.startswith("substr"):
# 解析 substr 的参数并截取字符串
match = re.match(r"substr\(([^,]+),\s*([^,]+),\s*([^)]+)\)", string_func)
if match:
start = int(match.group(2)) - 1 # substr 的起始位置从 1 开始
length = int(match.group(3))
if start < 0:
start = 0
if start + length > len(val):
length = len(val) - start
expected = val[start : start + length]
else:
expected = None
tdLog.info(f"string_func: {string_func}, val: {val}, expected: {expected}")
# check result
tdSql.checkResultsByFunc(
sql=f"select * from {self.stream}",
func=lambda: tdSql.getRows() == 1
and tdSql.compareData(
0,
2,
expected,
),
)
tdLog.info("test string function done.")