Repository: cassandra-dtest Updated Branches: refs/heads/master 104835d88 -> c0d9c9744
Add basic tests for fqltool replay+compare Patch by marcuse; reviewed by Stefan Podkowinski for CASSANDRA-14690 Project: http://git-wip-us.apache.org/repos/asf/cassandra-dtest/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra-dtest/commit/c0d9c974 Tree: http://git-wip-us.apache.org/repos/asf/cassandra-dtest/tree/c0d9c974 Diff: http://git-wip-us.apache.org/repos/asf/cassandra-dtest/diff/c0d9c974 Branch: refs/heads/master Commit: c0d9c97442434806ae074d0de3605366effc2e60 Parents: 104835d Author: Marcus Eriksson <[email protected]> Authored: Wed Sep 5 09:33:35 2018 +0200 Committer: Marcus Eriksson <[email protected]> Committed: Fri Oct 19 08:43:10 2018 +0200 ---------------------------------------------------------------------- fqltool_test.py | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra-dtest/blob/c0d9c974/fqltool_test.py ---------------------------------------------------------------------- diff --git a/fqltool_test.py b/fqltool_test.py new file mode 100644 index 0000000..f175e58 --- /dev/null +++ b/fqltool_test.py @@ -0,0 +1,159 @@ +import pytest +import logging +import os +import subprocess +import tempfile + +from dtest import Tester +from shutil import rmtree + +since = pytest.mark.since +logger = logging.getLogger(__name__) + + +@since('4.0') +class TestFQLTool(Tester): + """ + Makes sure fqltool replay and fqltool compare work + @jira_ticket CASSANDRA-14690 + """ + def test_replay(self): + """ + Generates a full query log, wipes the nodes and replays the + query log, then makes sure that the data is correct. + @jira_ticket CASSANDRA-14690 + """ + self.cluster.populate(2).start(wait_for_binary_proto=True) + node1, node2 = self.cluster.nodelist() + + with tempfile.TemporaryDirectory() as temp_dir: + tmpdir = tempfile.mkdtemp(dir=temp_dir) + tmpdir2 = tempfile.mkdtemp(dir=temp_dir) + node1.nodetool("enablefullquerylog --path={}".format(tmpdir)) + node2.nodetool("enablefullquerylog --path={}".format(tmpdir2)) + node1.stress(['write', 'n=1000']) + node1.flush() + node2.flush() + node1.nodetool("disablefullquerylog") + node2.nodetool("disablefullquerylog") + node1.stop(wait_other_notice=True) + node2.stop(wait_other_notice=True) + node1.clear() + node2.clear() + + node1.start(wait_for_binary_proto=True) + node2.start(wait_for_binary_proto=True, wait_other_notice=True) + # make sure the node is empty: + got_exception = False + try: + node1.stress(['read', 'n=1000']) + except Exception: + got_exception = True + assert got_exception + # replay the log files + self._run_fqltool_replay(node1, [tmpdir, tmpdir2], "127.0.0.1", None, None) + # and verify the data is there + node1.stress(['read', 'n=1000']) + + def test_compare(self): + """ + uses fqltool replay to compare two runs of the same query log and makes + sure that the results match + @jira_ticket CASSANDRA-14690 + """ + self.cluster.populate(1).start(wait_for_binary_proto=True) + node1 = self.cluster.nodelist()[0] + + with tempfile.TemporaryDirectory() as temp_dir: + results1 = tempfile.mkdtemp(dir=temp_dir) + queries1 = tempfile.mkdtemp(dir=temp_dir) + results2 = tempfile.mkdtemp(dir=temp_dir) + queries2 = tempfile.mkdtemp(dir=temp_dir) + fqldir = tempfile.mkdtemp(dir=temp_dir) + + node1.stress(['write', 'n=1000']) + node1.flush() + node1.nodetool("enablefullquerylog --path={}".format(fqldir)) + node1.stress(['read', 'n=1000']) + node1.nodetool("disablefullquerylog") + self._run_fqltool_replay(node1, [fqldir], "127.0.0.1", queries1, results1) + self._run_fqltool_replay(node1, [fqldir], "127.0.0.1", queries2, results2) + output = self._run_fqltool_compare(node1, queries1, [results1, results2]) + assert b"MISMATCH" not in output # running the same reads against the same data + + def test_compare_mismatch(self): + """ + generates two fql log files with different data (seq is different when running stress) + then asserts that the replays of each generates a mismatch + @jira_ticket CASSANDRA-14690 + """ + self.cluster.populate(1).start(wait_for_binary_proto=True) + node1 = self.cluster.nodelist()[0] + + with tempfile.TemporaryDirectory() as temp_dir: + fqldir1 = tempfile.mkdtemp(dir=temp_dir) + fqldir2 = tempfile.mkdtemp(dir=temp_dir) + results1 = tempfile.mkdtemp(dir=temp_dir) + queries1 = tempfile.mkdtemp(dir=temp_dir) + results2 = tempfile.mkdtemp(dir=temp_dir) + queries2 = tempfile.mkdtemp(dir=temp_dir) + + node1.nodetool("enablefullquerylog --path={}".format(fqldir1)) + node1.stress(['write', 'n=1000']) + node1.flush() + node1.stress(['read', 'n=1000']) + node1.nodetool("disablefullquerylog") + + node1.stop() + for d in node1.data_directories(): + rmtree(d) + os.mkdir(d) + node1.start(wait_for_binary_proto=True) + + node1.nodetool("enablefullquerylog --path={}".format(fqldir2)) + node1.stress(['write', 'n=1000', '-pop', 'seq=1000..2000']) + node1.flush() + node1.stress(['read', 'n=1000', '-pop', 'seq=1000..2000']) + node1.nodetool("disablefullquerylog") + node1.stop() + for d in node1.data_directories(): + rmtree(d) + os.mkdir(d) + node1.start(wait_for_binary_proto=True) + + self._run_fqltool_replay(node1, [fqldir1], "127.0.0.1", queries1, results1) + node1.stop() + for d in node1.data_directories(): + rmtree(d) + os.mkdir(d) + node1.start(wait_for_binary_proto=True) + self._run_fqltool_replay(node1, [fqldir2], "127.0.0.1", queries2, results2) + + output = self._run_fqltool_compare(node1, queries1, [results1, results2]) + assert b"MISMATCH" in output # compares two different stress runs, should mismatch + + def _run_fqltool_replay(self, node, logdirs, target, queries, results): + fqltool = self.fqltool(node) + args = [fqltool, "replay", "--target {}".format(target)] + if queries is not None: + args.append("--store-queries {}".format(queries)) + if results is not None: + args.append("--results {}".format(results)) + args.extend(logdirs) + rc = subprocess.call(args) + assert rc == 0 + + def _run_fqltool_compare(self, node, queries, results): + fqltool = self.fqltool(node) + args = [fqltool, "compare", "--queries {}".format(queries)] + args.extend([os.path.join(r, "127.0.0.1") for r in results]) + logger.info(args) + p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = p.communicate() + logger.info(stdout) + return stdout + + def fqltool(self, node): + cdir = node.get_install_dir() + fqltool = os.path.join(cdir, 'tools', 'bin', 'fqltool') + return fqltool --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
