mirror of
https://github.com/RRZE-HPC/OSACA.git
synced 2025-12-16 00:50:06 +01:00
Black formatting
This commit is contained in:
@@ -94,7 +94,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
instr7 = "fadd v17.2d, v16.2d, v1.2d"
|
||||
instr8 = "mov.d x0, v16.d[1]"
|
||||
instr9 = "ccmp x0, x1, #4, cc"
|
||||
|
||||
|
||||
parsed_1 = self.parser.parse_instruction(instr1)
|
||||
parsed_2 = self.parser.parse_instruction(instr2)
|
||||
parsed_3 = self.parser.parse_instruction(instr3)
|
||||
@@ -104,19 +104,19 @@ class TestParserAArch64(unittest.TestCase):
|
||||
parsed_7 = self.parser.parse_instruction(instr7)
|
||||
parsed_8 = self.parser.parse_instruction(instr8)
|
||||
parsed_9 = self.parser.parse_instruction(instr9)
|
||||
|
||||
|
||||
self.assertEqual(parsed_1.instruction, "vcvt.F32.S32")
|
||||
self.assertEqual(parsed_1.operands[0].name, "1")
|
||||
self.assertEqual(parsed_1.operands[0].prefix, "w")
|
||||
self.assertEqual(parsed_1.operands[1].name, "2")
|
||||
self.assertEqual(parsed_1.operands[1].prefix, "w")
|
||||
self.assertEqual(parsed_1.comment, "12.27")
|
||||
|
||||
|
||||
self.assertEqual(parsed_2.instruction, "b.lo")
|
||||
self.assertEqual(parsed_2.operands[0]['identifier']['name'], "..B1.4")
|
||||
self.assertEqual(parsed_2.operands[0]["identifier"]["name"], "..B1.4")
|
||||
self.assertEqual(len(parsed_2.operands), 1)
|
||||
self.assertIsNone(parsed_2.comment)
|
||||
|
||||
|
||||
self.assertEqual(parsed_3.instruction, "mov")
|
||||
self.assertEqual(parsed_3.operands[0].name, "2")
|
||||
self.assertEqual(parsed_3.operands[0].prefix, "x")
|
||||
@@ -127,8 +127,8 @@ class TestParserAArch64(unittest.TestCase):
|
||||
self.assertIsNone(parsed_4.operands[1].offset)
|
||||
self.assertEqual(parsed_4.operands[1].base.name, "sp")
|
||||
self.assertEqual(parsed_4.operands[1].base.prefix, "x")
|
||||
self.assertEqual(parsed_4.operands[1].index['name'], "1")
|
||||
self.assertEqual(parsed_4.operands[1].index['prefix'], "x")
|
||||
self.assertEqual(parsed_4.operands[1].index["name"], "1")
|
||||
self.assertEqual(parsed_4.operands[1].index["prefix"], "x")
|
||||
self.assertEqual(parsed_4.operands[1].scale, 16)
|
||||
self.assertEqual(parsed_4.operands[0].name, "28")
|
||||
self.assertEqual(parsed_4.operands[0].prefix, "x")
|
||||
@@ -137,8 +137,8 @@ class TestParserAArch64(unittest.TestCase):
|
||||
self.assertEqual(parsed_5.instruction, "ldr")
|
||||
self.assertEqual(parsed_5.operands[0].name, "0")
|
||||
self.assertEqual(parsed_5.operands[0].prefix, "x")
|
||||
self.assertEqual(parsed_5.operands[1].offset['identifier']['name'], "q2c")
|
||||
self.assertEqual(parsed_5.operands[1].offset['identifier']['relocation'], ":got_lo12:")
|
||||
self.assertEqual(parsed_5.operands[1].offset["identifier"]["name"], "q2c")
|
||||
self.assertEqual(parsed_5.operands[1].offset["identifier"]["relocation"], ":got_lo12:")
|
||||
self.assertEqual(parsed_5.operands[1].base.name, "0")
|
||||
self.assertEqual(parsed_5.operands[1].base.prefix, "x")
|
||||
self.assertIsNone(parsed_5.operands[1].index)
|
||||
@@ -147,8 +147,8 @@ class TestParserAArch64(unittest.TestCase):
|
||||
self.assertEqual(parsed_6.instruction, "adrp")
|
||||
self.assertEqual(parsed_6.operands[0].name, "0")
|
||||
self.assertEqual(parsed_6.operands[0].prefix, "x")
|
||||
self.assertEqual(parsed_6.operands[1]['identifier']['relocation'], ":got:")
|
||||
self.assertEqual(parsed_6.operands[1]['identifier']['name'], "visited")
|
||||
self.assertEqual(parsed_6.operands[1]["identifier"]["relocation"], ":got:")
|
||||
self.assertEqual(parsed_6.operands[1]["identifier"]["name"], "visited")
|
||||
|
||||
self.assertEqual(parsed_7.instruction, "fadd")
|
||||
self.assertEqual(parsed_7.operands[0].name, "17")
|
||||
@@ -168,8 +168,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
self.assertEqual(parsed_9.instruction, "ccmp")
|
||||
self.assertEqual(parsed_9.operands[0].name, "0")
|
||||
self.assertEqual(parsed_9.operands[0].prefix, "x")
|
||||
self.assertEqual(parsed_9.operands[3]['condition'], "CC")
|
||||
|
||||
self.assertEqual(parsed_9.operands[3]["condition"], "CC")
|
||||
|
||||
def test_parse_line(self):
|
||||
line_comment = "// -- Begin main"
|
||||
@@ -216,7 +215,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
RegisterOperand(PREFIX_ID="s", NAME_ID="0"),
|
||||
MemoryOperand(
|
||||
OFFSET_ID=None,
|
||||
BASE_ID=RegisterOperand(PREFIX_ID = "x", NAME_ID ="11"),
|
||||
BASE_ID=RegisterOperand(PREFIX_ID="x", NAME_ID="11"),
|
||||
INDEX_ID={
|
||||
"prefix": "w",
|
||||
"name": "10",
|
||||
@@ -239,7 +238,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
{"prfop": {"type": ["PLD"], "target": ["L1"], "policy": ["KEEP"]}},
|
||||
MemoryOperand(
|
||||
OFFSET_ID={"value": 2048},
|
||||
BASE_ID=RegisterOperand(PREFIX_ID = "x", NAME_ID ="26"),
|
||||
BASE_ID=RegisterOperand(PREFIX_ID="x", NAME_ID="26"),
|
||||
INDEX_ID=None,
|
||||
SCALE_ID=1,
|
||||
),
|
||||
@@ -257,7 +256,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
RegisterOperand(PREFIX_ID="x", NAME_ID="30"),
|
||||
MemoryOperand(
|
||||
OFFSET_ID={"value": -16},
|
||||
BASE_ID=RegisterOperand(NAME_ID = "sp", PREFIX_ID = "x"),
|
||||
BASE_ID=RegisterOperand(NAME_ID="sp", PREFIX_ID="x"),
|
||||
INDEX_ID=None,
|
||||
SCALE_ID=1,
|
||||
PRE_INDEXED=True,
|
||||
@@ -276,7 +275,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
RegisterOperand(PREFIX_ID="q", NAME_ID="3"),
|
||||
MemoryOperand(
|
||||
OFFSET_ID=None,
|
||||
BASE_ID=RegisterOperand(NAME_ID = "11", PREFIX_ID = "x"),
|
||||
BASE_ID=RegisterOperand(NAME_ID="11", PREFIX_ID="x"),
|
||||
INDEX_ID=None,
|
||||
SCALE_ID=1,
|
||||
POST_INDEXED={"value": 64},
|
||||
@@ -317,7 +316,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
LINE="ccmn x11, #1, #3, eq",
|
||||
LINE_NUMBER=9,
|
||||
)
|
||||
|
||||
|
||||
parsed_1 = self.parser.parse_line(line_comment, 1)
|
||||
parsed_2 = self.parser.parse_line(line_label, 2)
|
||||
parsed_3 = self.parser.parse_line(line_directive, 3)
|
||||
@@ -337,7 +336,6 @@ class TestParserAArch64(unittest.TestCase):
|
||||
self.assertEqual(parsed_7, instruction_form_7)
|
||||
self.assertEqual(parsed_8, instruction_form_8)
|
||||
self.assertEqual(parsed_9, instruction_form_9)
|
||||
|
||||
|
||||
def test_parse_file(self):
|
||||
parsed = self.parser.parse_file(self.triad_code)
|
||||
@@ -399,22 +397,22 @@ class TestParserAArch64(unittest.TestCase):
|
||||
# self.assertEqual(p_single.operands, reg_list_single)
|
||||
|
||||
def test_reg_dependency(self):
|
||||
reg_1_1 = RegisterOperand(PREFIX_ID = "b", NAME_ID = "1")
|
||||
reg_1_2 = RegisterOperand(PREFIX_ID = "h", NAME_ID = "1")
|
||||
reg_1_3 = RegisterOperand(PREFIX_ID = "s", NAME_ID = "1")
|
||||
reg_1_4 = RegisterOperand(PREFIX_ID = "d", NAME_ID = "1")
|
||||
reg_1_4 = RegisterOperand(PREFIX_ID = "q", NAME_ID = "1")
|
||||
reg_2_1 = RegisterOperand(PREFIX_ID = "w", NAME_ID = "2")
|
||||
reg_2_2 = RegisterOperand(PREFIX_ID = "x", NAME_ID = "2")
|
||||
reg_v1_1 = RegisterOperand(PREFIX_ID = "v", NAME_ID = "11", LANES = "16", SHAPE = "b")
|
||||
reg_v1_2 = RegisterOperand(PREFIX_ID = "v", NAME_ID = "11", LANES = "8", SHAPE = "h")
|
||||
reg_v1_3 = RegisterOperand(PREFIX_ID = "v", NAME_ID = "11", LANES = "4", SHAPE = "s")
|
||||
reg_v1_4 = RegisterOperand(PREFIX_ID = "v", NAME_ID = "11", LANES = "2", SHAPE = "d")
|
||||
reg_1_1 = RegisterOperand(PREFIX_ID="b", NAME_ID="1")
|
||||
reg_1_2 = RegisterOperand(PREFIX_ID="h", NAME_ID="1")
|
||||
reg_1_3 = RegisterOperand(PREFIX_ID="s", NAME_ID="1")
|
||||
reg_1_4 = RegisterOperand(PREFIX_ID="d", NAME_ID="1")
|
||||
reg_1_4 = RegisterOperand(PREFIX_ID="q", NAME_ID="1")
|
||||
reg_2_1 = RegisterOperand(PREFIX_ID="w", NAME_ID="2")
|
||||
reg_2_2 = RegisterOperand(PREFIX_ID="x", NAME_ID="2")
|
||||
reg_v1_1 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="16", SHAPE="b")
|
||||
reg_v1_2 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="8", SHAPE="h")
|
||||
reg_v1_3 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="4", SHAPE="s")
|
||||
reg_v1_4 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="2", SHAPE="d")
|
||||
|
||||
reg_b5 = RegisterOperand(PREFIX_ID = "b", NAME_ID = "5")
|
||||
reg_q15 = RegisterOperand(PREFIX_ID = "q", NAME_ID = "15")
|
||||
reg_v10 = RegisterOperand(PREFIX_ID = "v", NAME_ID = "10", LANES = "2", SHAPE = "s")
|
||||
reg_v20 = RegisterOperand(PREFIX_ID = "v", NAME_ID = "20", LANES = "2", SHAPE = "d")
|
||||
reg_b5 = RegisterOperand(PREFIX_ID="b", NAME_ID="5")
|
||||
reg_q15 = RegisterOperand(PREFIX_ID="q", NAME_ID="15")
|
||||
reg_v10 = RegisterOperand(PREFIX_ID="v", NAME_ID="10", LANES="2", SHAPE="s")
|
||||
reg_v20 = RegisterOperand(PREFIX_ID="v", NAME_ID="20", LANES="2", SHAPE="d")
|
||||
|
||||
reg_1 = [reg_1_1, reg_1_2, reg_1_3, reg_1_4]
|
||||
reg_2 = [reg_2_1, reg_2_2]
|
||||
|
||||
@@ -259,22 +259,22 @@ class TestParserX86ATT(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_reg_dependency(self):
|
||||
reg_a1 = RegisterOperand(NAME_ID = "rax")
|
||||
reg_a2 = RegisterOperand(NAME_ID = "eax")
|
||||
reg_a3 = RegisterOperand(NAME_ID = "ax")
|
||||
reg_a4 = RegisterOperand(NAME_ID = "al")
|
||||
reg_r11 = RegisterOperand(NAME_ID = "r11")
|
||||
reg_r11b = RegisterOperand(NAME_ID = "r11b")
|
||||
reg_r11d = RegisterOperand(NAME_ID = "r11d")
|
||||
reg_r11w = RegisterOperand(NAME_ID = "r11w")
|
||||
reg_xmm1 = RegisterOperand(NAME_ID = "xmm1")
|
||||
reg_ymm1 = RegisterOperand(NAME_ID = "ymm1")
|
||||
reg_zmm1 = RegisterOperand(NAME_ID = "zmm1")
|
||||
reg_a1 = RegisterOperand(NAME_ID="rax")
|
||||
reg_a2 = RegisterOperand(NAME_ID="eax")
|
||||
reg_a3 = RegisterOperand(NAME_ID="ax")
|
||||
reg_a4 = RegisterOperand(NAME_ID="al")
|
||||
reg_r11 = RegisterOperand(NAME_ID="r11")
|
||||
reg_r11b = RegisterOperand(NAME_ID="r11b")
|
||||
reg_r11d = RegisterOperand(NAME_ID="r11d")
|
||||
reg_r11w = RegisterOperand(NAME_ID="r11w")
|
||||
reg_xmm1 = RegisterOperand(NAME_ID="xmm1")
|
||||
reg_ymm1 = RegisterOperand(NAME_ID="ymm1")
|
||||
reg_zmm1 = RegisterOperand(NAME_ID="zmm1")
|
||||
|
||||
reg_b1 = RegisterOperand(NAME_ID = "rbx")
|
||||
reg_r15 = RegisterOperand(NAME_ID = "r15")
|
||||
reg_xmm2 = RegisterOperand(NAME_ID = "xmm2")
|
||||
reg_ymm3 = RegisterOperand(NAME_ID = "ymm3")
|
||||
reg_b1 = RegisterOperand(NAME_ID="rbx")
|
||||
reg_r15 = RegisterOperand(NAME_ID="r15")
|
||||
reg_xmm2 = RegisterOperand(NAME_ID="xmm2")
|
||||
reg_ymm3 = RegisterOperand(NAME_ID="ymm3")
|
||||
|
||||
reg_a = [reg_a1, reg_a2, reg_a3, reg_a4]
|
||||
reg_r = [reg_r11, reg_r11b, reg_r11d, reg_r11w]
|
||||
|
||||
@@ -22,6 +22,7 @@ from osaca.semantics import (
|
||||
from osaca.parser.register import RegisterOperand
|
||||
from osaca.parser.memory import MemoryOperand
|
||||
|
||||
|
||||
class TestSemanticTools(unittest.TestCase):
|
||||
MODULE_DATA_DIR = os.path.join(
|
||||
os.path.dirname(os.path.split(os.path.abspath(__file__))[0]), "osaca/data/"
|
||||
@@ -117,14 +118,14 @@ class TestSemanticTools(unittest.TestCase):
|
||||
###########
|
||||
# Tests
|
||||
###########
|
||||
|
||||
|
||||
def test_creation_by_name(self):
|
||||
try:
|
||||
tmp_mm = MachineModel(arch="CSX")
|
||||
ArchSemantics(tmp_mm)
|
||||
except ValueError:
|
||||
self.fail()
|
||||
'''
|
||||
"""
|
||||
def test_machine_model_various_functions(self):
|
||||
# check dummy MachineModel creation
|
||||
try:
|
||||
@@ -184,8 +185,9 @@ class TestSemanticTools(unittest.TestCase):
|
||||
"fadd register(prefix:v,shape:s),register(prefix:v,shape:s),"
|
||||
+ "register(prefix:v,shape:s)",
|
||||
)
|
||||
'''
|
||||
'''
|
||||
"""
|
||||
|
||||
"""
|
||||
# test get_store_tp
|
||||
self.assertEqual(
|
||||
test_mm_x86.get_store_throughput(
|
||||
@@ -246,7 +248,8 @@ class TestSemanticTools(unittest.TestCase):
|
||||
with open("/dev/null", "w") as dev_null:
|
||||
test_mm_x86.dump(stream=dev_null)
|
||||
test_mm_arm.dump(stream=dev_null)
|
||||
'''
|
||||
"""
|
||||
|
||||
def test_src_dst_assignment_x86(self):
|
||||
for instruction_form in self.kernel_x86:
|
||||
with self.subTest(instruction_form=instruction_form):
|
||||
@@ -272,7 +275,7 @@ class TestSemanticTools(unittest.TestCase):
|
||||
self.assertTrue(instruction_form.latency != None)
|
||||
self.assertIsInstance(instruction_form.port_pressure, list)
|
||||
self.assertEqual(len(instruction_form.port_pressure), port_num)
|
||||
|
||||
|
||||
def test_tp_lt_assignment_AArch64(self):
|
||||
self.assertTrue("ports" in self.machine_model_tx2)
|
||||
port_num = len(self.machine_model_tx2["ports"])
|
||||
@@ -282,7 +285,8 @@ class TestSemanticTools(unittest.TestCase):
|
||||
self.assertTrue(instruction_form.latency != None)
|
||||
self.assertIsInstance(instruction_form.port_pressure, list)
|
||||
self.assertEqual(len(instruction_form.port_pressure), port_num)
|
||||
'''
|
||||
|
||||
"""
|
||||
def test_optimal_throughput_assignment(self):
|
||||
# x86
|
||||
kernel_fixed = deepcopy(self.kernel_x86)
|
||||
@@ -392,7 +396,8 @@ class TestSemanticTools(unittest.TestCase):
|
||||
dg.get_dependent_instruction_forms()
|
||||
# test dot creation
|
||||
dg.export_graph(filepath="/dev/null")
|
||||
'''
|
||||
"""
|
||||
|
||||
def test_kernelDG_SVE(self):
|
||||
KernelDG(
|
||||
self.kernel_aarch64_SVE,
|
||||
@@ -401,7 +406,7 @@ class TestSemanticTools(unittest.TestCase):
|
||||
self.semantics_a64fx,
|
||||
)
|
||||
# TODO check for correct analysis
|
||||
|
||||
|
||||
def test_hidden_load(self):
|
||||
machine_model_hld = MachineModel(
|
||||
path_to_yaml=self._find_file("hidden_load_machine_model.yml")
|
||||
@@ -422,7 +427,7 @@ class TestSemanticTools(unittest.TestCase):
|
||||
self.assertEqual(num_hidden_loads, 1)
|
||||
self.assertEqual(num_hidden_loads_2, 0)
|
||||
self.assertEqual(num_hidden_loads_3, 1)
|
||||
|
||||
|
||||
def test_cyclic_dag(self):
|
||||
dg = KernelDG(self.kernel_x86, self.parser_x86, self.machine_model_csx, self.semantics_csx)
|
||||
dg.dg.add_edge(100, 101, latency=1.0)
|
||||
@@ -432,7 +437,8 @@ class TestSemanticTools(unittest.TestCase):
|
||||
dg.get_critical_path()
|
||||
with self.assertRaises(NotImplementedError):
|
||||
dg.get_loopcarried_dependencies()
|
||||
'''
|
||||
|
||||
"""
|
||||
def test_loop_carried_dependency_aarch64(self):
|
||||
dg = KernelDG(
|
||||
self.kernel_aarch64_memdep,
|
||||
@@ -534,12 +540,13 @@ class TestSemanticTools(unittest.TestCase):
|
||||
self.assertTrue(time_10 > 10)
|
||||
self.assertTrue(2 < time_2)
|
||||
self.assertTrue(time_2 < (time_10 - 7))
|
||||
'''
|
||||
"""
|
||||
|
||||
def test_is_read_is_written_x86(self):
|
||||
# independent form HW model
|
||||
dag = KernelDG(self.kernel_x86, self.parser_x86, None, None)
|
||||
reg_rcx = RegisterOperand(NAME_ID = "rcx")
|
||||
reg_ymm1 = RegisterOperand(NAME_ID = "ymm1")
|
||||
reg_rcx = RegisterOperand(NAME_ID="rcx")
|
||||
reg_ymm1 = RegisterOperand(NAME_ID="ymm1")
|
||||
|
||||
instr_form_r_c = self.parser_x86.parse_line("vmovsd %xmm0, (%r15,%rcx,8)")
|
||||
self.semantics_csx.assign_src_dst(instr_form_r_c)
|
||||
@@ -569,11 +576,11 @@ class TestSemanticTools(unittest.TestCase):
|
||||
def test_is_read_is_written_AArch64(self):
|
||||
# independent form HW model
|
||||
dag = KernelDG(self.kernel_AArch64, self.parser_AArch64, None, None)
|
||||
reg_x1 = RegisterOperand(PREFIX_ID="x",NAME_ID="1")
|
||||
reg_w1 = RegisterOperand(PREFIX_ID="w",NAME_ID="1")
|
||||
reg_d1 = RegisterOperand(PREFIX_ID="d",NAME_ID="1")
|
||||
reg_q1 = RegisterOperand(PREFIX_ID="q",NAME_ID="1")
|
||||
reg_v1 = RegisterOperand(PREFIX_ID="v",NAME_ID="1",LANES="2",SHAPE="d")
|
||||
reg_x1 = RegisterOperand(PREFIX_ID="x", NAME_ID="1")
|
||||
reg_w1 = RegisterOperand(PREFIX_ID="w", NAME_ID="1")
|
||||
reg_d1 = RegisterOperand(PREFIX_ID="d", NAME_ID="1")
|
||||
reg_q1 = RegisterOperand(PREFIX_ID="q", NAME_ID="1")
|
||||
reg_v1 = RegisterOperand(PREFIX_ID="v", NAME_ID="1", LANES="2", SHAPE="d")
|
||||
regs = [reg_d1, reg_q1, reg_v1]
|
||||
regs_gp = [reg_w1, reg_x1]
|
||||
|
||||
@@ -596,7 +603,7 @@ class TestSemanticTools(unittest.TestCase):
|
||||
|
||||
for reg in regs:
|
||||
with self.subTest(reg=reg):
|
||||
#self.assertTrue(dag.is_read(reg, instr_form_r_1))
|
||||
# self.assertTrue(dag.is_read(reg, instr_form_r_1))
|
||||
self.assertTrue(dag.is_read(reg, instr_form_r_2))
|
||||
self.assertTrue(dag.is_read(reg, instr_form_rw_1))
|
||||
self.assertFalse(dag.is_read(reg, instr_form_rw_2))
|
||||
@@ -638,7 +645,12 @@ class TestSemanticTools(unittest.TestCase):
|
||||
|
||||
def test_MachineModel_getter(self):
|
||||
sample_operands = [
|
||||
MemoryOperand(OFFSET_ID=None,BASE_ID=RegisterOperand(NAME_ID = "r12"), INDEX_ID=RegisterOperand(NAME_ID="rcx"),SCALE_ID=8)
|
||||
MemoryOperand(
|
||||
OFFSET_ID=None,
|
||||
BASE_ID=RegisterOperand(NAME_ID="r12"),
|
||||
INDEX_ID=RegisterOperand(NAME_ID="rcx"),
|
||||
SCALE_ID=8,
|
||||
)
|
||||
]
|
||||
self.assertIsNone(self.machine_model_csx.get_instruction("GETRESULT", sample_operands))
|
||||
self.assertIsNone(self.machine_model_tx2.get_instruction("GETRESULT", sample_operands))
|
||||
@@ -675,4 +687,4 @@ class TestSemanticTools(unittest.TestCase):
|
||||
|
||||
if __name__ == "__main__":
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestSemanticTools)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
||||
Reference in New Issue
Block a user