jj/cli/tests/test_parallelize_command.rs

591 lines
20 KiB
Rust
Raw Normal View History

// Copyright 2024 The Jujutsu Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::path::Path;
use crate::common::TestEnvironment;
#[test]
fn test_parallelize_no_descendants() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
for n in 1..6 {
test_env.jj_cmd_ok(&workspace_path, &["commit", &format!("-m{n}")]);
}
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=6"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ b911505e443e 6
2e00cb15c7b6 5
9df3c87db1a2 4
9f5b59fa4622 3
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
test_env.jj_cmd_ok(&workspace_path, &["parallelize", "description(1)::"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 6c7b60a45eb6 6
296f48966777 5
524062469789 4
a9334ecaa379 3
3a7b37ebe843 2
761e67df44b7 1
000000000000
"###);
}
// Only the head commit has descendants.
#[test]
fn test_parallelize_with_descendants_simple() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
for n in 1..6 {
test_env.jj_cmd_ok(&workspace_path, &["commit", &format!("-m{n}")]);
}
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=6"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ b911505e443e 6
2e00cb15c7b6 5
9df3c87db1a2 4
9f5b59fa4622 3
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
test_env.jj_cmd_ok(
&workspace_path,
&["parallelize", "description(1)::description(4)"],
);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ f28f986c7134 6
21e9963ac5ff 5
524062469789 4
a9334ecaa379 3
3a7b37ebe843 2
761e67df44b7 1
000000000000
"###);
}
// One of the commits being parallelized has a child that isn't being
// parallelized. That child will become a merge of any ancestors which are being
// parallelized.
#[test]
fn test_parallelize_where_interior_has_non_target_children() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
for n in 1..6 {
test_env.jj_cmd_ok(&workspace_path, &["commit", &format!("-m{n}")]);
}
test_env.jj_cmd_ok(&workspace_path, &["new", "description(2)", "-m=2c"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "description(5)", "-m=6"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ d27ee705f7a9 6
2e00cb15c7b6 5
9df3c87db1a2 4
9f5b59fa4622 3
9c8865930f3c 2c
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
test_env.jj_cmd_ok(&workspace_path, &["parallelize", "dc0::9df"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 9f1bec0d6c46 6
7dd2f5648395 5
b8f977c12383 4
7be8374575b9 3
679fc870858c 2c
96ce11389312 2
2bfe3fe3e472 1
000000000000
"###);
}
#[test]
fn test_parallelize_where_root_has_non_target_children() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
for n in 1..4 {
test_env.jj_cmd_ok(&workspace_path, &["commit", &format!("-m{n}")]);
}
test_env.jj_cmd_ok(&workspace_path, &["new", "description(1)", "-m=1c"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "description(3)", "-m=4"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 7636b3f489f4 4
9f5b59fa4622 3
d826910d21fb 2
50e2ced81124 1c
dc0e5d6135ce 1
000000000000
"###);
test_env.jj_cmd_ok(
&workspace_path,
&["parallelize", "description(1)::description(3)"],
);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
ad35c9caf4fb 1c
@ 6ee674074e23 4
5bd049136a7c 3
60f737a5a4a7 2
79ebcd81a1ee 1
000000000000
"###);
}
// One of the commits being parallelized has a child that is a merge commit.
#[test]
fn test_parallelize_with_merge_commit_child() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "1"]);
for n in 2..4 {
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", &n.to_string()]);
}
test_env.jj_cmd_ok(&workspace_path, &["new", "root()", "-m", "a"]);
test_env.jj_cmd_ok(
&workspace_path,
&["new", "description(2)", "description(a)", "-m", "2a-c"],
);
test_env.jj_cmd_ok(&workspace_path, &["new", "description(3)", "-m", "4"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 90a65779e2ec 4
9f5b59fa4622 3
a01c1fad8506 2a-c
1eb902150bb9 a
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
// After this finishes, child-2a will have three parents: "1", "2", and "a".
test_env.jj_cmd_ok(
&workspace_path,
&["parallelize", "description(1)::description(3)"],
);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 5a0dd49510d1 4
a9334ecaa379 3
605371712469 2a-c
1eb902150bb9 a
3a7b37ebe843 2
761e67df44b7 1
000000000000
"###);
}
#[test]
fn test_parallelize_failure_disconnected_target_commits() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
for n in 1..3 {
test_env.jj_cmd_ok(&workspace_path, &["commit", &format!("-m{n}")]);
}
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=3"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 9f5b59fa4622 3
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
insta::assert_snapshot!(test_env.jj_cmd_failure(
&workspace_path, &["parallelize", "description(1)", "description(3)"]),@r###"
Error: Cannot parallelize since the target revisions are not connected.
"###);
}
#[test]
fn test_parallelize_head_is_a_merge() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=1"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=2"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "root()"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=a"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=b"]);
test_env.jj_cmd_ok(
&workspace_path,
&["new", "description(2)", "description(b)", "-m=merged-head"],
);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 1a8db14a8cf0 merged-head
401e43e9461f b
66ea2ab19a70 a
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
insta::assert_snapshot!(test_env.jj_cmd_failure(&workspace_path,&["parallelize", "description(1)::"]),
@r###"
Error: Only the roots of the target revset are allowed to have parents which are not being parallelized.
"###);
}
#[test]
fn test_parallelize_interior_target_is_a_merge() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=1"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "root()", "-m=a"]);
test_env.jj_cmd_ok(
&workspace_path,
&["new", "description(1)", "description(a)", "-m=2"],
);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=3"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 299099c22761 3
0c4da981fc0a 2
6d37472c632c a
dc0e5d6135ce 1
000000000000
"###);
insta::assert_snapshot!(test_env.jj_cmd_failure(&workspace_path,&["parallelize", "description(1)::"]),
@r###"
Error: Only the roots of the target revset are allowed to have parents which are not being parallelized.
"###);
}
#[test]
fn test_parallelize_root_is_a_merge() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=y"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "root()", "-m=x"]);
test_env.jj_cmd_ok(
&workspace_path,
&["new", "description(y)", "description(x)", "-m=1"],
);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=2"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=3"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 9f66b50aa1f2 3
dd995ce87f21 2
4b4941342e06 1
4035b23c8f72 x
f3ec359cf9ff y
000000000000
"###);
test_env.jj_cmd_ok(
&workspace_path,
&["parallelize", "description(1)::description(2)"],
);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 4e81469adb0d 3
38945baf55f4 2
9b1a1927720c 1
4035b23c8f72 x
f3ec359cf9ff y
000000000000
"###);
}
#[test]
fn test_parallelize_multiple_heads() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=0"]);
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=1"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "description(0)", "-m=2"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 8314addde180 2
a915696cf0ad 1
a56846756248 0
000000000000
"###);
test_env.jj_cmd_ok(&workspace_path, &["parallelize", "description(0)::"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ e84481c26195 2
2047527ade93 1
9d0c0750973c 0
000000000000
"###);
}
// All heads must have the same children as the other heads, but only if they
// have children. In this test only one head has children, so the command
// succeeds.
#[test]
fn test_parallelize_multiple_heads_with_and_without_children() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=0"]);
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=1"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "description(0)", "-m=2"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 8314addde180 2
a915696cf0ad 1
a56846756248 0
000000000000
"###);
test_env.jj_cmd_ok(
&workspace_path,
&["parallelize", "description(0)", "description(1)"],
);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 49fe9e130d15 2
9d0c0750973c 0
2047527ade93 1
000000000000
"###);
}
#[test]
fn test_parallelize_multiple_roots() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m=1"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "root()", "-m=a"]);
test_env.jj_cmd_ok(
&workspace_path,
&["new", "description(1)", "description(a)", "-m=2"],
);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=3"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 299099c22761 3
0c4da981fc0a 2
6d37472c632c a
dc0e5d6135ce 1
000000000000
"###);
// Succeeds because the roots have the same parents.
test_env.jj_cmd_ok(&workspace_path, &["parallelize", "root().."]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 3c90598481cd 3
b96aa55582e5 2
3178394e33e7 a
1d9a0895e7d6 1
000000000000
"###);
}
#[test]
fn test_parallelize_failure_multiple_heads_with_different_children() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=1"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=2"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=3"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "root()"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=a"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=b"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=c"]);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 9b5fa4b364d4
7b095ae9b21f c
5164ab888473 b
f16fe8ac5ce9 a
9f5b59fa4622 3
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
insta::assert_snapshot!(
test_env.jj_cmd_failure(
&workspace_path,
&[
"parallelize",
"description(1)::description(2)",
"description(a)::description(b)",
],
),@r###"
Error: All heads of the target revisions must have the same children.
"###);
}
#[test]
fn test_parallelize_failure_multiple_roots_with_different_parents() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=1"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=2"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "root()"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=a"]);
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m=b"]);
test_env.jj_cmd_ok(
&workspace_path,
&["new", "description(2)", "description(b)", "-m=merged-head"],
);
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
@ 1a8db14a8cf0 merged-head
401e43e9461f b
66ea2ab19a70 a
d826910d21fb 2
dc0e5d6135ce 1
000000000000
"###);
insta::assert_snapshot!(
test_env.jj_cmd_failure(
&workspace_path,
&["parallelize", "description(2)::", "description(b)::"],
),@r###"
Error: All roots of the target revisions must have the same parents.
"###);
}
#[test]
fn test_parallelize_complex_nonlinear_target() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let workspace_path = test_env.env_root().join("repo");
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=0", "root()"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=1", "description(0)"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=2", "description(0)"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=3", "description(0)"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=4", "all:heads(..)"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=1c", "description(1)"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=2c", "description(2)"]);
test_env.jj_cmd_ok(&workspace_path, &["new", "-m=3c", "description(3)"]);
insta::assert_snapshot!(get_log_output_with_parents(&test_env, &workspace_path), @r###"
@ b043eb81416c 3c parents: 3
48277ee9afe0 4 parents: 3 2 1
944922f0c69f 3 parents: 0
9d28e8e38435 2c parents: 2
97d7522f40e8 2 parents: 0
6c82c22a5e35 1c parents: 1
0c058af014a6 1 parents: 0
745bea8029c1 0 parents:
000000000000 parents:
"###);
let (_stdout, stderr) = test_env.jj_cmd_ok(
&workspace_path,
&["parallelize", "description(0)::description(4)"],
);
insta::assert_snapshot!(stderr, @r###"
Working copy now at: yostqsxw d193f3b7 (empty) 3c
Parent commit : rlvkpnrz cbb4e169 (empty) 0
Parent commit : mzvwutvl cb944786 (empty) 3
"###);
insta::assert_snapshot!(get_log_output_with_parents(&test_env, &workspace_path), @r###"
@ d193f3b72495 3c parents: 0 3
cb9447869bf0 3 parents:
80fbafb56917 2c parents: 0 2
8f4b8ef68676 2 parents:
1985e0427139 1c parents: 0 1
82918d78c984 1 parents:
cbb4e1692ef4 0 parents:
14ca4df576b3 4 parents:
000000000000 parents:
"###)
}
fn get_log_output_with_parents(test_env: &TestEnvironment, cwd: &Path) -> String {
let template = r#"
separate(" ",
commit_id.short(),
description.first_line(),
"parents:",
parents.map(|c|c.description().first_line())
)"#;
test_env.jj_cmd_success(cwd, &["log", "-T", template])
}
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
let template = r#"separate(" ", commit_id.short(), local_branches, description)"#;
test_env.jj_cmd_success(cwd, &["log", "-T", template])
}