def execute_query( sql, expected=None, format="TabSeparatedWithNames", compare_func=None ): """Execute SQL query and compare the output to the snapshot.""" name = basename(current().name) with When("I execute query", description=sql): r = current().context.node.query(sql + " FORMAT " + format) if expected is not None: with Then("I check output against expected"): if compare_func is None: assert r.output.strip() == expected, error() else: assert compare_func(r.output.strip(), expected), error() else: with Then("I check output against snapshot"): with values() as that: assert that( snapshot( "\n" + r.output.strip() + "\n", "tests", name=name, encoder=str ) ), error()
def encryption(self): """Check that `encrypt` functions accepts `plaintext` as the second parameter with any data type and `mode` as the first parameter. """ key = f"{'1' * 36}" iv = f"{'2' * 16}" aad = "some random aad" for mode, key_len, iv_len, aad_len in modes: for datatype, plaintext in plaintexts: requirement = globals().get( f"""RQ_SRS008_AES_Encrypt_Function_Parameters_Mode_Value_{mode.strip("'").replace("-","_").upper()}""" )("1.0") with Example( f"""mode={mode.strip("'")} datatype={datatype.strip("'")} iv={iv_len} aad={aad_len}""", requirements=[requirement]) as example: r = encrypt(plaintext=plaintext, key=f"'{key[:key_len]}'", mode=mode, iv=(None if not iv_len else f"'{iv[:iv_len]}'"), aad=(None if not aad_len else f"'{aad}'")) with Then("I check output against snapshot"): with values() as that: example_name = basename(example.name) assert that( snapshot( r.output.strip(), "encrypt", name=f"example_{example_name.replace(' ', '_')}" )), error()
def encryption(self): """Check that `aes_encrypt_mysql` functions accepts `plaintext` as the second parameter with any data type and `mode` as the first parameter. """ key = f"{'1' * 64}" iv = f"{'2' * 64}" for mode, key_len, iv_len in mysql_modes: for datatype, plaintext in plaintexts: with Example( f"""mode={mode.strip("'")} datatype={datatype.strip("'")} key={key_len} iv={iv_len}""" ) as example: r = aes_encrypt_mysql( plaintext=plaintext, key=f"'{key[:key_len]}'", mode=mode, iv=(None if not iv_len else f"'{iv[:iv_len]}'"), ) with Then("I check output against snapshot"): with values() as that: example_name = basename(example.name) assert that( snapshot( r.output.strip(), "encrypt_mysql", name= f"example_{example_name.replace(' ', '_')}", )), error()
def help_flag(self): """Test that CLI help option exists. """ backup = self.context.backup with When("I run clickhouse-backup with no arguments"): r = backup.cmd(f"clickhouse-backup --help") snap = "".join([ s for s in r.output.split('\n\n') if s != "" and "VERSION" not in s ]) with Then("I expect snapshot to match"): with values() as that: assert that(snapshot(snap, "cli", name="help_flag")), error()
def usage(self): """Test that CLI usage scenario remains the same. """ backup = self.context.backup with When("I run clickhouse-backup with no arguments"): r = backup.cmd(f"clickhouse-backup") snap = "".join([ s for s in r.output.split('\n\n') if s != "" and "VERSION" not in s ]) with Then("I expect snapshot to match"): with values() as that: assert that(snapshot(snap, "cli", name="cli_usage")), error()
def aes_encrypt_mysql_using_materialized_view(self): """Check that we can use `aes_encrypt_mysql` function when inserting data into a table using a materialized view for input data transformation. """ node = self.context.node key = f"{'1' * 64}" iv = f"{'2' * 64}" aad = "some random aad" for mode, key_len, iv_len in mysql_modes: with Example(f"""mode={mode.strip("'")} key={key_len} iv={iv_len}""" ) as example: example_key = f"'{key[:key_len]}'" example_mode = mode example_iv = None if not iv_len else f"'{iv[:iv_len]}'" example_transform = ( f"aes_encrypt_mysql(mode, secret, key{', iv' if example_iv else ''})" ) with table("user_data"): with mv_transform("user_data", example_transform): with When("I insert encrypted data"): node.query(f""" INSERT INTO user_data_input (date, name, secret, mode, key) VALUES ('2020-01-01', 'user0', 'user0_secret', {example_mode}, {example_key}{(", " + example_iv) if example_iv else ""}), ('2020-01-02', 'user1', 'user1_secret', {example_mode}, {example_key}{(", " + example_iv) if example_iv else ""}), ('2020-01-03', 'user2', 'user2_secret', {example_mode}, {example_key}{(", " + example_iv) if example_iv else ""}) """) with And("I read inserted data back"): node.query( "SELECT date, name, hex(secret) FROM user_data ORDER BY date" ) with Then("output must match the snapshot"): with values() as that: assert that( snapshot( r.output.strip(), "insert", name= f"aes_encrypt_mysql_mv_example_{varname(basename(self.name))}", )), error()
def default_config(self): """Test that default config remains the same. """ backup = self.context.backup with When("I run clickhouse-backup with no arguments"): r = backup.cmd(f"clickhouse-backup default-config").output with Then("I expect snapshot to match"): with values() as that: assert that( snapshot(str([ e for e in r.split('\n') if not ("concurrency" in e or "max" in e) ]), "cli", name="default_config")), error()
def encrypt_using_input_table_function(self): """Check that we can use `encrypt` function when inserting data into a table using insert select and `input()` table function. """ node = self.context.node key = f"{'1' * 36}" iv = f"{'2' * 16}" aad = "some random aad" for mode, key_len, iv_len, aad_len in modes: with Example(f"""mode={mode.strip("'")} iv={iv_len} aad={aad_len}""" ) as example: example_key = f"'{key[:key_len]}'" example_mode = mode example_iv = None if not iv_len else f"'{iv[:iv_len]}'" example_aad = None if not aad_len else f"'{aad}'" example_transform = f"encrypt({mode}, secret, {example_key}{(', ' + example_iv) if example_iv else ''}{(', ' + example_aad) if example_aad else ''})" with table("user_data"): with When("I insert encrypted data"): node.query(f""" INSERT INTO user_data SELECT date, name, {example_transform} FROM input('date Date, name String, secret String') FORMAT Values ('2020-01-01', 'user0', 'user0_secret'), ('2020-01-02', 'user1', 'user1_secret'), ('2020-01-03', 'user2', 'user2_secret') """) with And("I read inserted data back"): r = node.query( "SELECT date, name, hex(secret) FROM user_data ORDER BY date" ) with Then("output must match the snapshot"): with values() as that: assert that( snapshot( r.output.strip(), "insert", name= f"encrypt_input_example_{varname(basename(example.name))}", )), error()
def shell(self): """Suite of Shell tests. """ stress_count = self.context.stress_count with Given("import"): from testflows.connect import Shell with Test("open"): with Shell() as bash: pass with Test("execute command"): with Shell() as bash: bash("ls -la") with Test("custom shell name"): with Shell(name="shell") as shell: shell("ls -la") with Test("execute command with custom name"): with Shell() as bash: bash("ls -la", name="ls") with Test("execute multiple commands"): with Shell() as bash: bash("echo Hello World") bash("ls -la") bash("echo Bye World") with Test("execute command with utf-8"): with Shell() as bash: bash("echo Gãńdåłf_Thê_Gręât") with Test("share the same shell between different tests"): with Shell() as bash: with Step("first test"): bash("echo Hello World") with Step("second test"): bash("ls -la") with Step("third test"): bash("echo Bye World") with Test("check command output"): with Shell() as bash: with Step("one line output"): assert bash( "echo Hello World").output == "Hello World", error() with Step("empty output"): assert bash("echo ").output == "", error() with Step("multi line output"): text = "line1\\nline2" with values() as that: assert that( bash(f"echo -e \"{text}\"").output) == text.replace( "\\n", "\n"), error() with Test("check command exitcode"): with Shell() as bash: with Step("exit code 0"): assert bash("ls -la").exitcode == 0, error() with Step("exit code 2"): assert bash("ls /foo__").exitcode == 2, error() with Test("check timeout"): with Shell() as bash: bash.timeout = 6 with Step("timeout 1 sec"): bash("echo hello; sleep 0.75; " * 5) with Test("async command"): with Shell() as bash: with bash("tail -f /proc/cpuinfo", asyncronous=True) as tail: tail.readlines() with Test("async command with custom name"): with Shell() as bash: with bash("tail -f /proc/cpuinfo", asyncronous=True, name="cpuinfo") as tail: tail.readlines() with Test("check double prompts before command"): with Shell() as bash: bash.send("") bash("ls") with Test("check double prompts after command"): with Shell() as bash: for i in range(100): bash.send("") bash("ls\r\n") bash("ls; echo -e 'bash# \nbash# '") with Test("check empty lines before command"): with Shell() as bash: for i in range(stress_count): bash("\n\n\necho \"foo\"") with Test("check empty lines after command"): with Shell() as bash: for i in range(stress_count): bash("echo \"foo\"\n\n\n") with Test("check empty lines between commands"): with Shell() as bash: bash.timeout = 1 with raises(ExpectTimeoutError): bash("echo \"foo\"\n\n\necho\"foo\"") with Test("check empty lines before and after command"): with Shell() as bash: for i in range(stress_count): bash("\n\n\necho \"foo\"\n\n\n") with Test("check multiline command"): with Shell() as bash: for i in range(stress_count): bash("cat << HEREDOC > foo\nline 1\nline 2\nline 3\nHEREDOC") with Test("check matching long command (manual)"): def check(command): with Shell(command=command, name=" ".join(command), new_prompt="terminal# ") as bash: for i in range(2048): cmd = f"echo \"{'a'*i}\"" bash.expect(bash.prompt) bash.send(cmd) bash.expect(re.escape(cmd)) bash.expect(bash.prompt) bash.send("\r", eol="") with Example("sh"): check(["/bin/sh"]) with Example("bash --noediting"): check(["/bin/bash", "--noediting"]) with Example("bash"): check(["/bin/bash"]) with Test("check matching long command"): def check(command): with Shell(command=command, name=" ".join(command), new_prompt="terminal# ") as bash: for i in range(2048): c = bash(f"echo \"{'a'*i}\"") assert c.output == f"{'a'*i}", error() with Example("sh"): check(["/bin/sh"]) with Example("bash --noediting"): check(["/bin/bash", "--noediting"]) with Example("bash"): check(["/bin/bash"]) with Test("check multiline command with long lines"): with Shell() as bash: cmd = ( "cat << HEREDOC > foo\n" "'111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111', '22222222222222222'\n" "'22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222', '33333333333333333'\n" "HEREDOC") for i in range(stress_count): bash(cmd) with Test("check multiline command using echo -e with long lines"): with Shell() as bash: cmd = textwrap.dedent(""" echo -e " SELECT hex( aes_decrypt_mysql( 'aes-256-cbc', dictGet('default.dict_user_data', 'secret', toUInt64(1)), '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111', '22222222222222222$ ) ) " """) for i in range(stress_count): bash(cmd) with Test("check subshell"): with Shell() as bash: with Check("first subshell"): with bash.subshell("bash --noediting") as sub_bash: sub_bash("ls -la") bash("ls -la") with Check("second subshell"): with bash.subshell("bash --noediting") as sub_bash: sub_bash("ls -la") bash("ls -la")