Skip to content

Commit

Permalink
cat/play: tip that multiple files can be processed
Browse files Browse the repository at this point in the history
Closes #1018
Closes #1019
  • Loading branch information
patapenka-alexey committed Nov 20, 2024
1 parent c5c65e1 commit a0b1cb8
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 107 deletions.
4 changes: 2 additions & 2 deletions cli/cmd/cat.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ var catFlags = checkpoint.Opts{
func NewCatCmd() *cobra.Command {
var catCmd = &cobra.Command{
Use: "cat <FILE>...",
Short: "Print into stdout the contents of .snap/.xlog files",
Short: "Print into stdout the contents of .snap/.xlog FILE(s)",
Run: func(cmd *cobra.Command, args []string) {
cmdCtx.CommandName = cmd.Name()
err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo,
internalCatModule, args)
util.HandleCmdErr(cmd, err)
},
Example: "tt cat /path/to/xlog --timestamp 2024-11-13T14:02:36.818700000+00:00\n" +
" tt cat /path/to/snap --timestamp=1731592956.818",
" tt cat /path/to/1.snap /path/to/2.snap --timestamp=1731592956.818",
}

catCmd.Flags().Uint64Var(&catFlags.To, "to", catFlags.To,
Expand Down
4 changes: 2 additions & 2 deletions cli/cmd/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ var (
func NewPlayCmd() *cobra.Command {
var playCmd = &cobra.Command{
Use: "play <URI> <FILE>...",
Short: "Play the contents of .snap/.xlog files to another Tarantool instance",
Short: "Play the contents of .snap/.xlog FILE(s) to another Tarantool instance",
Run: func(cmd *cobra.Command, args []string) {
cmdCtx.CommandName = cmd.Name()
err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo,
internalPlayModule, args)
util.HandleCmdErr(cmd, err)
},
Example: "tt play uri /path/to/xlog --timestamp 2024-11-13T14:02:36.818700000+00:00\n" +
" tt play uri /path/to/xlog --timestamp=1731592956.818",
" tt play uri /path/to/1.xlog /path/to/2.xlog --timestamp=1731592956.818",
}

playCmd.Flags().StringVarP(&playUsername, "username", "u", "", "username")
Expand Down
103 changes: 58 additions & 45 deletions test/integration/cat/test_cat.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,65 @@

from utils import run_command_and_get_output

TEST_CAT_ARGS_CCONFIG = ("args, cat_result, found, not_found")

def test_cat_unset_arg(tt_cmd, tmp_path):
# Testing with unset .xlog or .snap file.
cmd = [tt_cmd, "cat"]
rc, output = run_command_and_get_output(cmd, cwd=tmp_path)
assert rc == 1
assert re.search(r"it is required to specify at least one .xlog or .snap file", output)


def test_cat_non_existent_file(tt_cmd, tmp_path):
# Testing with non-existent .xlog or .snap file.
cmd = [tt_cmd, "cat", "path-to-non-existent-file"]
rc, output = run_command_and_get_output(cmd, cwd=tmp_path)
assert rc == 1
assert re.search(r"No such file or directory", output)


def test_cat_snap_file(tt_cmd, tmp_path):
# Copy the .snap file to the "run" directory.
test_app_path = os.path.join(os.path.dirname(__file__), "test_file", "test.snap")
shutil.copy(test_app_path, tmp_path)

# Testing .snap file.
cmd = [
tt_cmd, "cat", "test.snap", "--show-system",
"--space=320", "--space=296", "--from=423", "--to=513"
]
rc, output = run_command_and_get_output(cmd, cwd=tmp_path)
assert rc == 0
assert re.search(r"lsn: 423", output)
assert re.search(r"lsn: 512", output)
assert re.search(r"space_id: 320", output)
assert re.search(r"space_id: 296", output)
def make_test_cat_args_param(
args=[],
cat_result=0,
found={},
not_found={},
):
return pytest.param(args, cat_result, found, not_found)


def test_cat_xlog_file(tt_cmd, tmp_path):
@pytest.mark.parametrize(TEST_CAT_ARGS_CCONFIG, [
make_test_cat_args_param(
# Testing with unset .xlog or .snap file.
cat_result=1,
found={"it is required to specify at least one .xlog or .snap file"},
),
make_test_cat_args_param(
args=["path-to-non-existent-file"],
cat_result=1,
found={"No such file or directory"},
),
make_test_cat_args_param(
args=["test.snap", "--show-system", "--space=320",
"--space=296", "--from=423", "--to=513"],
cat_result=0,
found={"lsn: 423",
"lsn: 512",
"space_id: 320",
"space_id: 296"},
),
make_test_cat_args_param(
args=["test.xlog", "--show-system", "--replica=1"],
cat_result=0,
found={"replica_id: 1"},
),
make_test_cat_args_param(
args=["test.xlog", "test.snap"],
cat_result=0,
found={"Result of cat: the file \"test.xlog\" is processed below",
"Result of cat: the file \"test.snap\" is processed below"},
),
])
def test_cat_args_tests(tt_cmd, tmp_path, args, cat_result, found, not_found):
# Copy the .xlog file to the "run" directory.
test_app_path = os.path.join(os.path.dirname(__file__), "test_file", "test.xlog")
shutil.copy(test_app_path, tmp_path)
test_xlog_file = os.path.join(os.path.dirname(__file__), "test_file", "test.xlog")
test_snap_file = os.path.join(os.path.dirname(__file__), "test_file", "test.snap")
shutil.copy(test_xlog_file, tmp_path)
shutil.copy(test_snap_file, tmp_path)

# Testing .xlog file.
cmd = [tt_cmd, "cat", "test.xlog", "--show-system", "--replica=1"]
cmd = [tt_cmd, "cat"]
cmd.extend(args)
rc, output = run_command_and_get_output(cmd, cwd=tmp_path)
assert rc == 0
assert re.search(r"replica_id: 1", output)
assert rc == cat_result
for item in found:
assert re.search(r"{0}".format(item), output)
for item in not_found:
assert not re.search(r"{0}".format(item), output)


TEST_CAT_TIMESTAMP_PARAMS_CCONFIG = ("input, cat_result, found, not_found")
Expand Down Expand Up @@ -106,17 +120,16 @@ def make_test_cat_timestamp_param(
"timestamp: 1731592956.8184"},
),
])
def test_cat_test_remote_instance_timestamp(tt_cmd, tmp_path, input,
cat_result, found, not_found):
def test_cat_test_timestamp(tt_cmd, tmp_path, input,
cat_result, found, not_found):
# Copy the .xlog file to the "run" directory.
test_app_path = os.path.join(os.path.dirname(__file__), "test_file", "timestamp.xlog")
shutil.copy(test_app_path, tmp_path)

cmd = [tt_cmd, "cat", "timestamp.xlog", "--timestamp={0}".format(input)]
rc, output = run_command_and_get_output(cmd, cwd=tmp_path)
assert rc == cat_result
if cat_result == 0:
for item in found:
assert re.search(r"{0}".format(item), output)
for item in not_found:
assert not re.search(r"{0}".format(item), output)
for item in found:
assert re.search(r"{0}".format(item), output)
for item in not_found:
assert not re.search(r"{0}".format(item), output)
107 changes: 49 additions & 58 deletions test/integration/play/test_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ def test_instance(request, tmp_path):
return inst


def test_play_unset_arg(tt_cmd, tmp_path):
# Testing with unset uri and .xlog or .snap file.
cmd = [tt_cmd, "play"]
rc, output = run_command_and_get_output(cmd, cwd=tmp_path)
assert rc == 1
assert re.search(r"required to specify an URI and at least one .xlog or .snap file", output)


def test_play_non_existent_uri(tt_cmd, tmp_path):
# Testing with non-existent uri.
cmd = [tt_cmd, "play", "127.0.0.1:0", "_"]
Expand All @@ -37,100 +29,99 @@ def test_play_non_existent_uri(tt_cmd, tmp_path):
assert re.search(r"no connection to the host", output)


def test_play_non_existent_file(tt_cmd, tmp_path, test_instance):
# Run play with non-existent file.
cmd = [tt_cmd, "play", "127.0.0.1:" + test_instance.port, "path-to-non-existent-file"]
rc, output = run_command_and_get_output(cmd, cwd=tmp_path)
assert rc == 1
assert re.search(r"No such file or directory", output)


def test_play_test_remote_instance(tt_cmd, test_instance):
# Play .xlog file to the remote instance.
cmd = [tt_cmd, "play", "127.0.0.1:" + test_instance.port, "test.xlog", "--space=999"]
rc, output = run_command_and_get_output(cmd, cwd=test_instance._tmpdir)
assert rc == 0
assert re.search(r"Play result: completed successfully", output)

# Testing played .xlog file from the remote instance.
cmd = [tt_cmd, "cat", "00000000000000000000.xlog", "--space=999"]
rc, output = run_command_and_get_output(cmd, cwd=test_instance._tmpdir)
assert rc == 0
assert re.search(r"space_id: 999", output)
assert re.search(r"[1, 'Roxette', 1986]", output)
assert re.search(r"[2, 'Scorpions', 2015]", output)
assert re.search(r"[3, 'Ace of Base', 1993]", output)


TEST_PLAY_TIMESTAMP_PARAMS_CCONFIG = ("input, play_result, found, not_found")
TEST_PLAY_PARAMS_CCONFIG = ("args, play_result, play_error, found, not_found")


def make_test_play_timestamp_param(
input="",
args=[],
play_result=0,
play_error="",
found={},
not_found={},
):
return pytest.param(input, play_result, found, not_found)
return pytest.param(args, play_result, play_error, found, not_found)


@pytest.mark.parametrize(TEST_PLAY_TIMESTAMP_PARAMS_CCONFIG, [
@pytest.mark.parametrize(TEST_PLAY_PARAMS_CCONFIG, [
make_test_play_timestamp_param(
input="abcdef",
# Testing with unset uri and .xlog or .snap file.
play_result=1,
found={"failed to parse a timestamp: parsing time \"abcdef\""},
play_error="required to specify an URI and at least one .xlog or .snap file",
),
make_test_play_timestamp_param(
input="2024-11-14T14:02:36.abc",
args=["path-to-non-existent-file"],
play_result=1,
found={"failed to parse a timestamp: parsing time \"2024-11-14T14:02:36.abc\""},
play_error="No such file or directory",
),
make_test_play_timestamp_param(
input="",
play_result=0,
# Testing with multiple files specified
args=["test.xlog", "test.xlog"],
play_result=1,
play_error="ER_TUPLE_FOUND: Duplicate key exists in unique index",
),
make_test_play_timestamp_param(
args=["test.xlog", "--timestamp=abcdef", "--space=999"],
play_result=1,
play_error="failed to parse a timestamp: parsing time \"abcdef\"",
),
make_test_play_timestamp_param(
args=["test.xlog", "--timestamp=2024-11-14T14:02:36.abc", "--space=999"],
play_result=1,
play_error="failed to parse a timestamp: parsing time \"2024-11-14T14:02:36.abc\"",
),
make_test_play_timestamp_param(
# Play .xlog file to the remote instance.
args=["test.xlog", "--space=999"],
found={"space_id: 999",
"[1, 'Roxette', 1986]",
"[2, 'Scorpions', 2015]",
"[3, 'Ace of Base', 1993]"},
),
make_test_play_timestamp_param(
# Testing timestamp default value.
args=["test.xlog", "--timestamp=", "--space=999"],
found={"[3, 'Ace of Base', 1993]"},
),
make_test_play_timestamp_param(
input="1651130533.1534",
play_result=0,
args=["test.xlog", "--timestamp=1651130533.1534", "--space=999"],
found={"space_id: 999",
"[1, 'Roxette', 1986]",
"[2, 'Scorpions', 2015]"},
not_found={"Ace of Base"},
),
make_test_play_timestamp_param(
input="2022-04-28T07:22:13.1534+00:00",
play_result=0,
args=["test.xlog", "--timestamp=1651130533.1534", "--space=999"],
found={"space_id: 999",
"[1, 'Roxette', 1986]",
"[2, 'Scorpions', 2015]"},
not_found={"Ace of Base"},
),
make_test_play_timestamp_param(
input="2022-04-28T07:22:12+00:00",
play_result=0,
args=["test.xlog", "--timestamp=2022-04-28T07:22:12+00:00", "--space=999"],
found={"space_id: 999",
"[1, 'Roxette', 1986]"},
not_found={"Scorpions",
"Ace of Base"},
),
])
def test_play_test_remote_instance_timestamp(tt_cmd, test_instance, input,
play_result, found, not_found):
def test_play_test_remote_instance_timestamp(tt_cmd, test_instance, args,
play_result, play_error, found, not_found):
# Play .xlog file to the remote instance.
cmd = [tt_cmd, "play", "127.0.0.1:" + test_instance.port, "test.xlog",
"--timestamp={0}".format(input), "--space=999"]
rc, output = run_command_and_get_output(cmd, cwd=test_instance._tmpdir)
cmd = [tt_cmd, "play", "127.0.0.1:" + test_instance.port]
cmd.extend(args)
rc, play_output = run_command_and_get_output(cmd, cwd=test_instance._tmpdir)
assert rc == play_result
if play_result == 0:
if play_result == 1:
assert re.search(r"{0}".format(play_error), play_output)
else:
# Testing played .xlog file from the remote instance.
cmd = [tt_cmd, "cat", "00000000000000000000.xlog", "--space=999"]
rc, output = run_command_and_get_output(cmd, cwd=test_instance._tmpdir)
rc, cat_output = run_command_and_get_output(cmd, cwd=test_instance._tmpdir)
assert rc == 0
for item in found:
assert re.search(r"{0}".format(item), output)
assert re.search(r"{0}".format(item), cat_output)
for item in not_found:
assert not re.search(r"{0}".format(item), output)
assert not re.search(r"{0}".format(item), cat_output)


@pytest.mark.parametrize("opts", [
Expand Down

0 comments on commit a0b1cb8

Please sign in to comment.