bugfix: Fixed testing issues

v4
suxb201 12 months ago committed by suxb201
parent 55e3c2c314
commit 992e593e6e
  1. 8
      .github/workflows/ci.yml
  2. 9
      internal/reader/scan_cluster_reader.go
  3. 9
      internal/reader/sync_cluster_reader.go
  4. 2
      test.sh
  5. 13
      tests/README.md
  6. 38
      tests/helpers/commands/tair_hash.py
  7. 28
      tests/helpers/commands/tair_string.py
  8. 30
      tests/helpers/commands/tair_zset.py
  9. 8
      tests/helpers/constant.py
  10. 4
      tests/helpers/data_inserter.py
  11. 6
      tests/helpers/redis.py

@ -1,11 +1,17 @@
name: CI name: CI
on: [ push, pull_request ] on:
push:
branches: [ v4 ]
pull_request:
branches: [ v4 ]
workflow_dispatch:
jobs: jobs:
black-box-test: black-box-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
max-parallel: 1
matrix: matrix:
redis-version: [ "2.8", "3.0", "4.0", "5.0", "6.0", "7.0" ] redis-version: [ "2.8", "3.0", "4.0", "5.0", "6.0", "7.0" ]
fail-fast: false fail-fast: false

@ -17,12 +17,9 @@ func NewScanClusterReader(opts *ScanReaderOptions) Reader {
rd := &scanClusterReader{} rd := &scanClusterReader{}
for _, address := range addresses { for _, address := range addresses {
rd.readers = append(rd.readers, NewScanStandaloneReader(&ScanReaderOptions{ theOpts := *opts
Address: address, theOpts.Address = address
Username: opts.Username, rd.readers = append(rd.readers, NewScanStandaloneReader(&theOpts))
Password: opts.Password,
Tls: opts.Tls,
}))
} }
return rd return rd
} }

@ -21,12 +21,9 @@ func NewSyncClusterReader(opts *SyncReaderOptions) Reader {
} }
rd := &syncClusterReader{} rd := &syncClusterReader{}
for _, address := range addresses { for _, address := range addresses {
rd.readers = append(rd.readers, NewSyncStandaloneReader(&SyncReaderOptions{ theOpts := *opts
Address: address, theOpts.Address = address
Username: opts.Username, rd.readers = append(rd.readers, NewSyncStandaloneReader(&theOpts))
Password: opts.Password,
Tls: opts.Tls,
}))
} }
return rd return rd
} }

@ -6,4 +6,4 @@ go test ./... -v
# black box test # black box test
cd tests/ cd tests/
pybbt cases pybbt cases --verbose --flags modules

@ -0,0 +1,13 @@
本项目使用 pybbt 工具进行黑盒测试。pybbt 是一个基于 Python 的工具,简化了软件的黑盒测试过程。要运行测试用例,请执行以下命令:
```bash
pybbt cases --verbose --flags modules
```
该命令将以详细日志记录的方式运行 cases 目录中的测试用例,并向测试用例传递 modules 标志。
如果本地没有安装 modules,可以不起用 modules 标志,这样就会跳过需要 modules 的测试用例:
```bash
pybbt cases --verbose
```
更多关于 pybbt 的信息、安装说明和用法示例,请参阅完整的文档: https://pypi.org/project/pybbt/

@ -1,8 +1,8 @@
import pybbt import pybbt
from helpers.commands.checker import Checker from helpers.commands.checker import Checker
from helpers.constant import REDIS_SERVER_MODULES_ENABLED
from helpers.redis import Redis from helpers.redis import Redis
from helpers.constant import REDIS_SERVER_VERSION
class TairHashChecker(Checker): class TairHashChecker(Checker):
@ -12,21 +12,22 @@ class TairHashChecker(Checker):
self.cnt = 0 self.cnt = 0
def add_data(self, r: Redis, cross_slots_cmd: bool): def add_data(self, r: Redis, cross_slots_cmd: bool):
if REDIS_SERVER_VERSION < 5.0: if not REDIS_SERVER_MODULES_ENABLED:
return return
p = r.pipeline() p = r.pipeline()
# different parameters type # different parameters type
p.execute_command("EXHSET",f"{self.PREFIX}_{self.cnt}", "field", "value") p.execute_command("EXHSET", f"{self.PREFIX}_{self.cnt}", "field", "value")
p.execute_command("EXHSET",f"{self.PREFIX}_{self.cnt}_ABS", "field_abs", "value_abs", "ABS", 2) p.execute_command("EXHSET", f"{self.PREFIX}_{self.cnt}_ABS", "field_abs", "value_abs", "ABS", 2)
p.execute_command("EXHSET",f"{self.PREFIX}_{self.cnt}_EX", "field_ex", "value_ex", "EX", 20000) p.execute_command("EXHSET", f"{self.PREFIX}_{self.cnt}_EX", "field_ex", "value_ex", "EX", 20000)
# different key # different key
# different field # different field
p.execute_command("EXHSET",f"{self.PREFIX}_{self.cnt}_ALL_01", "field_all_01", "value_all_01", "EX", 20000, "ABS", 2) p.execute_command("EXHSET", f"{self.PREFIX}_{self.cnt}_ALL_01", "field_all_01", "value_all_01", "EX", 20000, "ABS", 2)
p.execute_command("EXHSET",f"{self.PREFIX}_{self.cnt}_ALL_01", "field_all_02", "value_all_02", "EX", 20000, "ABS", 3) p.execute_command("EXHSET", f"{self.PREFIX}_{self.cnt}_ALL_01", "field_all_02", "value_all_02", "EX", 20000, "ABS", 3)
p.execute_command("EXHSET",f"{self.PREFIX}_{self.cnt}_ALL_02", "field_all_01", "value_all_01", "EX", 20000, "ABS", 2) p.execute_command("EXHSET", f"{self.PREFIX}_{self.cnt}_ALL_02", "field_all_01", "value_all_01", "EX", 20000, "ABS", 2)
p.execute_command("EXHSET",f"{self.PREFIX}_{self.cnt}_ALL_02", "field_all_02", "value_all_02", "EX", 20000, "ABS", 3) p.execute_command("EXHSET", f"{self.PREFIX}_{self.cnt}_ALL_02", "field_all_02", "value_all_02", "EX", 20000, "ABS", 3)
ret = p.execute() ret = p.execute()
# pybbt.ASSERT_EQ(ret, [b"1", b"1", b"1", b"1",b"1", b"1",b"1"]) # pybbt.ASSERT_EQ(ret, [b"1", b"1", b"1", b"1",b"1", b"1",b"1"])
@ -35,21 +36,22 @@ class TairHashChecker(Checker):
self.cnt += 1 self.cnt += 1
def check_data(self, r: Redis, cross_slots_cmd: bool): def check_data(self, r: Redis, cross_slots_cmd: bool):
if REDIS_SERVER_VERSION < 5.0: if not REDIS_SERVER_MODULES_ENABLED:
return return
for i in range(self.cnt): for i in range(self.cnt):
p = r.pipeline() p = r.pipeline()
p.execute_command("EXHGET",f"{self.PREFIX}_{i}", "field") p.execute_command("EXHGET", f"{self.PREFIX}_{i}", "field")
p.execute_command("EXHGET",f"{self.PREFIX}_{i}_ABS", "field_abs") p.execute_command("EXHGET", f"{self.PREFIX}_{i}_ABS", "field_abs")
p.execute_command("EXHGET",f"{self.PREFIX}_{i}_EX", "field_ex") p.execute_command("EXHGET", f"{self.PREFIX}_{i}_EX", "field_ex")
p.execute_command("EXHGET",f"{self.PREFIX}_{i}_ALL_01", "field_all_01") p.execute_command("EXHGET", f"{self.PREFIX}_{i}_ALL_01", "field_all_01")
p.execute_command("EXHGET",f"{self.PREFIX}_{i}_ALL_01", "field_all_02") p.execute_command("EXHGET", f"{self.PREFIX}_{i}_ALL_01", "field_all_02")
p.execute_command("EXHGET",f"{self.PREFIX}_{i}_ALL_02", "field_all_01") p.execute_command("EXHGET", f"{self.PREFIX}_{i}_ALL_02", "field_all_01")
p.execute_command("EXHGET",f"{self.PREFIX}_{i}_ALL_02", "field_all_02") p.execute_command("EXHGET", f"{self.PREFIX}_{i}_ALL_02", "field_all_02")
ret = p.execute() ret = p.execute()
# 需要确定一下如果一个命令返回多个值是如何封装的 # 需要确定一下如果一个命令返回多个值是如何封装的
pybbt.ASSERT_EQ(ret, [b"value", b"value_abs", b"value_ex", b"value_all_01", b"value_all_02", b"value_all_01", b"value_all_02",]) pybbt.ASSERT_EQ(ret, [b"value", b"value_abs", b"value_ex", b"value_all_01", b"value_all_02", b"value_all_01", b"value_all_02", ])

@ -1,8 +1,8 @@
import pybbt import pybbt
from helpers.commands.checker import Checker from helpers.commands.checker import Checker
from helpers.constant import REDIS_SERVER_MODULES_ENABLED
from helpers.redis import Redis from helpers.redis import Redis
from helpers.constant import REDIS_SERVER_VERSION
class TairStringChecker(Checker): class TairStringChecker(Checker):
@ -12,32 +12,34 @@ class TairStringChecker(Checker):
self.cnt = 0 self.cnt = 0
def add_data(self, r: Redis, cross_slots_cmd: bool): def add_data(self, r: Redis, cross_slots_cmd: bool):
if REDIS_SERVER_VERSION < 5.0: if not REDIS_SERVER_MODULES_ENABLED:
return return
p = r.pipeline() p = r.pipeline()
# different parameters type # different parameters type
p.execute_command("EXSET",f"{self.PREFIX}_{self.cnt}_ABS", "abs_value", "VER",2) p.execute_command("EXSET", f"{self.PREFIX}_{self.cnt}_ABS", "abs_value", "VER", 2)
p.execute_command("EXSET",f"{self.PREFIX}_{self.cnt}_FLAGS", "flags_value", "FLAGS", 2) p.execute_command("EXSET", f"{self.PREFIX}_{self.cnt}_FLAGS", "flags_value", "FLAGS", 2)
p.execute_command("Exset",f"{self.PREFIX}_{self.cnt}_EX", "ex_value", "EX", 20000) p.execute_command("Exset", f"{self.PREFIX}_{self.cnt}_EX", "ex_value", "EX", 20000)
# different key # different key
p.execute_command("Exset",f"{self.PREFIX}_{self.cnt}_ALL_01", "all_value_01", "EX", 20000, "ABS", 3, "FLAGS", 4) p.execute_command("Exset", f"{self.PREFIX}_{self.cnt}_ALL_01", "all_value_01", "EX", 20000, "ABS", 3, "FLAGS", 4)
p.execute_command("Exset",f"{self.PREFIX}_{self.cnt}_ALL_02", "all_value_02", "EX", 20000, "ABS", 4, "FLAGS", 5) p.execute_command("Exset", f"{self.PREFIX}_{self.cnt}_ALL_02", "all_value_02", "EX", 20000, "ABS", 4, "FLAGS", 5)
ret = p.execute() ret = p.execute()
pybbt.ASSERT_EQ(ret, [b"OK", b"OK", b"OK", b"OK", b"OK"]) pybbt.ASSERT_EQ(ret, [b"OK", b"OK", b"OK", b"OK", b"OK"])
self.cnt += 1 self.cnt += 1
def check_data(self, r: Redis, cross_slots_cmd: bool): def check_data(self, r: Redis, cross_slots_cmd: bool):
if REDIS_SERVER_VERSION < 5.0: if not REDIS_SERVER_MODULES_ENABLED:
return return
for i in range(self.cnt): for i in range(self.cnt):
p = r.pipeline() p = r.pipeline()
p.execute_command("EXGET",f"{self.PREFIX}_{i}_ABS") p.execute_command("EXGET", f"{self.PREFIX}_{i}_ABS")
p.execute_command("EXGET",f"{self.PREFIX}_{i}_FLAGS", "WITHFLAGS") p.execute_command("EXGET", f"{self.PREFIX}_{i}_FLAGS", "WITHFLAGS")
p.execute_command("EXGET",f"{self.PREFIX}_{i}_EX") p.execute_command("EXGET", f"{self.PREFIX}_{i}_EX")
p.execute_command("EXGET",f"{self.PREFIX}_{i}_ALL_01", "WITHFLAGS") p.execute_command("EXGET", f"{self.PREFIX}_{i}_ALL_01", "WITHFLAGS")
p.execute_command("EXGET",f"{self.PREFIX}_{i}_ALL_02", "WITHFLAGS") p.execute_command("EXGET", f"{self.PREFIX}_{i}_ALL_02", "WITHFLAGS")
ret = p.execute() ret = p.execute()
pybbt.ASSERT_EQ(ret, [[b"abs_value", 1], [b"flags_value", 1, 2], [b"ex_value", 1], [b"all_value_01", 3, 4], [b"all_value_02", 4, 5]]) pybbt.ASSERT_EQ(ret, [[b"abs_value", 1], [b"flags_value", 1, 2], [b"ex_value", 1], [b"all_value_01", 3, 4], [b"all_value_02", 4, 5]])

@ -1,8 +1,8 @@
import pybbt import pybbt
from helpers.commands.checker import Checker from helpers.commands.checker import Checker
from helpers.constant import REDIS_SERVER_MODULES_ENABLED
from helpers.redis import Redis from helpers.redis import Redis
from helpers.constant import REDIS_SERVER_VERSION
class TairZsetChecker(Checker): class TairZsetChecker(Checker):
@ -12,36 +12,38 @@ class TairZsetChecker(Checker):
self.cnt = 0 self.cnt = 0
def add_data(self, r: Redis, cross_slots_cmd: bool): def add_data(self, r: Redis, cross_slots_cmd: bool):
if REDIS_SERVER_VERSION < 5.0: if not REDIS_SERVER_MODULES_ENABLED:
return return
p = r.pipeline() p = r.pipeline()
# different key # different key
# int or float # int or float
p.execute_command("EXZADD",f"{self.PREFIX}_{self.cnt}_key01", "1.1#1.2", "mem01","2.2#2.3", "mem02") p.execute_command("EXZADD", f"{self.PREFIX}_{self.cnt}_key01", "1.1#1.2", "mem01", "2.2#2.3", "mem02")
p.execute_command("EXZADD",f"{self.PREFIX}_{self.cnt}_key01", "3.3#3.4", "mem03","4.4#4.5", "mem04") p.execute_command("EXZADD", f"{self.PREFIX}_{self.cnt}_key01", "3.3#3.4", "mem03", "4.4#4.5", "mem04")
p.execute_command("EXZADD",f"{self.PREFIX}_{self.cnt}_key02", "1.1#1.2", "mem01") p.execute_command("EXZADD", f"{self.PREFIX}_{self.cnt}_key02", "1.1#1.2", "mem01")
p.execute_command("EXZADD",f"{self.PREFIX}_{self.cnt}_key02", "2.2#2.3", "mem02") p.execute_command("EXZADD", f"{self.PREFIX}_{self.cnt}_key02", "2.2#2.3", "mem02")
ret = p.execute() ret = p.execute()
pybbt.ASSERT_EQ(ret, [2, 2, 1, 1]) pybbt.ASSERT_EQ(ret, [2, 2, 1, 1])
self.cnt += 1 self.cnt += 1
def check_data(self, r: Redis, cross_slots_cmd: bool): def check_data(self, r: Redis, cross_slots_cmd: bool):
if REDIS_SERVER_VERSION < 5.0: if not REDIS_SERVER_MODULES_ENABLED:
return return
for i in range(self.cnt): for i in range(self.cnt):
p = r.pipeline() p = r.pipeline()
p.execute_command("EXZSCORE",f"{self.PREFIX}_{i}_key01", "mem01") p.execute_command("EXZSCORE", f"{self.PREFIX}_{i}_key01", "mem01")
p.execute_command("EXZSCORE",f"{self.PREFIX}_{i}_key01", "mem02") p.execute_command("EXZSCORE", f"{self.PREFIX}_{i}_key01", "mem02")
p.execute_command("EXZSCORE",f"{self.PREFIX}_{i}_key01", "mem03") p.execute_command("EXZSCORE", f"{self.PREFIX}_{i}_key01", "mem03")
p.execute_command("EXZSCORE",f"{self.PREFIX}_{i}_key01", "mem04") p.execute_command("EXZSCORE", f"{self.PREFIX}_{i}_key01", "mem04")
p.execute_command("EXZSCORE",f"{self.PREFIX}_{i}_key02", "mem01") p.execute_command("EXZSCORE", f"{self.PREFIX}_{i}_key02", "mem01")
p.execute_command("EXZSCORE",f"{self.PREFIX}_{i}_key02", "mem02") p.execute_command("EXZSCORE", f"{self.PREFIX}_{i}_key02", "mem02")
ret = p.execute() ret = p.execute()
pybbt.ASSERT_EQ(ret, pybbt.ASSERT_EQ(ret,
[b'1.1000000000000001#1.2', [b'1.1000000000000001#1.2',
b'2.2000000000000002#2.2999999999999998', b'3.2999999999999998#3.3999999999999999', b'2.2000000000000002#2.2999999999999998', b'3.2999999999999998#3.3999999999999999',
b'4.4000000000000004#4.5', b'1.1000000000000001#1.2', b'4.4000000000000004#4.5', b'1.1000000000000001#1.2',
b'2.2000000000000002#2.2999999999999998'] ) b'2.2000000000000002#2.2999999999999998'])

@ -2,14 +2,20 @@ import shutil
import subprocess import subprocess
from pathlib import Path from pathlib import Path
BASE_PATH = f"{Path(__file__).parent.parent.parent.absolute()}" # project path import pybbt
BASE_PATH = f"{Path(__file__).parent.parent.parent.absolute()}" # project path
PATH_REDIS_SHAKE = f"{BASE_PATH}/bin/redis-shake" PATH_REDIS_SHAKE = f"{BASE_PATH}/bin/redis-shake"
PATH_REDIS_SERVER = shutil.which('redis-server') PATH_REDIS_SERVER = shutil.which('redis-server')
# REDIS_SERVER_VERSION
output = subprocess.check_output(f"{PATH_REDIS_SERVER} --version", shell=True) output = subprocess.check_output(f"{PATH_REDIS_SERVER} --version", shell=True)
output_str = output.decode("utf-8") output_str = output.decode("utf-8")
REDIS_SERVER_VERSION = float(output_str.split("=")[1].split(" ")[0][:3]) REDIS_SERVER_VERSION = float(output_str.split("=")[1].split(" ")[0][:3])
# REDIS_SERVER_MODULES_ENABLED
REDIS_SERVER_MODULES_ENABLED = REDIS_SERVER_VERSION >= 5.0 and "modules" in pybbt.get_global_flags()
if __name__ == '__main__': if __name__ == '__main__':
print(BASE_PATH) print(BASE_PATH)
print(PATH_REDIS_SHAKE) print(PATH_REDIS_SHAKE)

@ -1,6 +1,5 @@
from helpers.commands import SelectChecker, StringChecker, TairStringChecker, TairHashChecker, TairZsetChecker from helpers.commands import SelectChecker, StringChecker, TairHashChecker, TairStringChecker, TairZsetChecker
from helpers.redis import Redis from helpers.redis import Redis
from helpers.constant import PATH_REDIS_SERVER, REDIS_SERVER_VERSION
class DataInserter: class DataInserter:
@ -13,7 +12,6 @@ class DataInserter:
TairZsetChecker(), TairZsetChecker(),
] ]
def add_data(self, r: Redis, cross_slots_cmd: bool): def add_data(self, r: Redis, cross_slots_cmd: bool):
for checker in self.checkers: for checker in self.checkers:
checker.add_data(r, cross_slots_cmd) checker.add_data(r, cross_slots_cmd)

@ -3,7 +3,7 @@ import time
import pybbt import pybbt
import redis import redis
from helpers.constant import PATH_REDIS_SERVER, REDIS_SERVER_VERSION from helpers.constant import PATH_REDIS_SERVER, REDIS_SERVER_MODULES_ENABLED, REDIS_SERVER_VERSION
from helpers.utils.network import get_free_port from helpers.utils.network import get_free_port
from helpers.utils.timer import Timer from helpers.utils.timer import Timer
@ -18,13 +18,11 @@ class Redis:
self.dir = f"{self.case_ctx.dir}/redis_{self.port}" self.dir = f"{self.case_ctx.dir}/redis_{self.port}"
args.extend(["--port", str(self.port)]) args.extend(["--port", str(self.port)])
if REDIS_SERVER_VERSION > 4.0: if REDIS_SERVER_MODULES_ENABLED:
args.extend(["--loadmodule", "tairstring_module.so"]) args.extend(["--loadmodule", "tairstring_module.so"])
args.extend(["--loadmodule", "tairhash_module.so"]) args.extend(["--loadmodule", "tairhash_module.so"])
args.extend(["--loadmodule", "tairzset_module.so"]) args.extend(["--loadmodule", "tairzset_module.so"])
self.server = pybbt.Launcher(args=[PATH_REDIS_SERVER] + args, work_dir=self.dir) self.server = pybbt.Launcher(args=[PATH_REDIS_SERVER] + args, work_dir=self.dir)
else:
self.server = pybbt.Launcher(args=[PATH_REDIS_SERVER] + args, work_dir=self.dir)
self._wait_start() self._wait_start()
self.client = redis.Redis(host=self.host, port=self.port) self.client = redis.Redis(host=self.host, port=self.port)

Loading…
Cancel
Save