forked from mirrors/jj
view: add tests of merging views
I'm about to add some support for branches and tags (for issue #21) and it seems that we didn't have explicit testing of merging of views. There was `test_import_refs_merge()` in `test_git.rs` but that's specifically for git refs. It seems that it's made obsolete by the tests added by this commit, so I'm removing it.
This commit is contained in:
parent
9fb3521bf5
commit
b1e60b37ea
2 changed files with 155 additions and 50 deletions
|
@ -145,59 +145,10 @@ fn test_import_refs_reimport() {
|
|||
);
|
||||
}
|
||||
|
||||
fn git_ref(git_repo: &git2::Repository, name: &str, target: Oid) {
|
||||
git_repo.reference(name, target, true, "").unwrap();
|
||||
}
|
||||
|
||||
fn delete_git_ref(git_repo: &git2::Repository, name: &str) {
|
||||
git_repo.find_reference(name).unwrap().delete().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_refs_merge() {
|
||||
let settings = testutils::user_settings();
|
||||
let (_temp_dir, repo) = testutils::init_repo(&settings, true);
|
||||
let git_repo = repo.store().git_repo().unwrap();
|
||||
|
||||
let commit1 = empty_git_commit(&git_repo, "refs/heads/main", &[]);
|
||||
let commit2 = empty_git_commit(&git_repo, "refs/heads/main", &[&commit1]);
|
||||
let commit3 = empty_git_commit(&git_repo, "refs/heads/main", &[&commit2]);
|
||||
let commit4 = empty_git_commit(&git_repo, "refs/heads/feature1", &[&commit2]);
|
||||
let commit5 = empty_git_commit(&git_repo, "refs/heads/feature2", &[&commit2]);
|
||||
let mut tx = repo.start_transaction("initial import");
|
||||
jujutsu_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap();
|
||||
let repo = tx.commit();
|
||||
|
||||
// One of the concurrent operations:
|
||||
delete_git_ref(&git_repo, "refs/heads/feature1");
|
||||
git_ref(&git_repo, "refs/heads/main", commit4.id());
|
||||
let mut tx1 = repo.start_transaction("concurrent import 1");
|
||||
jujutsu_lib::git::import_refs(tx1.mut_repo(), &git_repo).unwrap();
|
||||
tx1.commit();
|
||||
|
||||
// The other concurrent operation:
|
||||
let mut tx2 = repo.start_transaction("concurrent import 2");
|
||||
git_ref(&git_repo, "refs/heads/main", commit5.id());
|
||||
jujutsu_lib::git::import_refs(tx2.mut_repo(), &git_repo).unwrap();
|
||||
tx2.commit();
|
||||
|
||||
// Reload the repo, causing the operations to be merged.
|
||||
let repo = repo.reload();
|
||||
|
||||
let view = repo.view();
|
||||
let git_refs = view.git_refs();
|
||||
assert_eq!(git_refs.len(), 2);
|
||||
assert_eq!(
|
||||
git_refs.get("refs/heads/main"),
|
||||
Some(RefTarget::Conflict {
|
||||
removes: vec![commit_id(&commit3)],
|
||||
adds: vec![commit_id(&commit4), commit_id(&commit5)]
|
||||
})
|
||||
.as_ref()
|
||||
);
|
||||
assert_eq!(git_refs.get("refs/heads/feature1"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_refs_empty_git_repo() {
|
||||
let settings = testutils::user_settings();
|
||||
|
|
|
@ -12,9 +12,10 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use jujutsu_lib::op_store::RefTarget;
|
||||
use jujutsu_lib::testutils;
|
||||
use jujutsu_lib::testutils::CommitGraphBuilder;
|
||||
use maplit::hashset;
|
||||
use maplit::{btreemap, hashset};
|
||||
use test_case::test_case;
|
||||
|
||||
#[test_case(false ; "local store")]
|
||||
|
@ -75,3 +76,156 @@ fn test_heads_merge(use_git: bool) {
|
|||
hashset! {wc.current_commit_id(), merge.id().clone()}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_merge_views_heads() {
|
||||
// Tests merging of the view's heads (by performing concurrent operations).
|
||||
let settings = testutils::user_settings();
|
||||
let (_temp_dir, repo) = testutils::init_repo(&settings, false);
|
||||
|
||||
let mut tx = repo.start_transaction("test");
|
||||
let mut_repo = tx.mut_repo();
|
||||
let head_unchanged = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
let head_remove_tx1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
let head_remove_tx2 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
let public_head_unchanged =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
mut_repo.add_public_head(&public_head_unchanged);
|
||||
let public_head_remove_tx1 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
mut_repo.add_public_head(&public_head_remove_tx1);
|
||||
let public_head_remove_tx2 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
mut_repo.add_public_head(&public_head_remove_tx2);
|
||||
let repo = tx.commit();
|
||||
|
||||
let mut tx1 = repo.start_transaction("test");
|
||||
tx1.mut_repo().remove_head(&head_remove_tx1);
|
||||
tx1.mut_repo().remove_public_head(&public_head_remove_tx1);
|
||||
let head_add_tx1 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(tx1.mut_repo());
|
||||
let public_head_add_tx1 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(tx1.mut_repo());
|
||||
tx1.mut_repo().add_public_head(&public_head_add_tx1);
|
||||
tx1.commit();
|
||||
|
||||
let mut tx2 = repo.start_transaction("test");
|
||||
tx2.mut_repo().remove_head(&head_remove_tx2);
|
||||
tx2.mut_repo().remove_public_head(&public_head_remove_tx2);
|
||||
let head_add_tx2 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(tx2.mut_repo());
|
||||
let public_head_add_tx2 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(tx2.mut_repo());
|
||||
tx2.mut_repo().add_public_head(&public_head_add_tx2);
|
||||
tx2.commit();
|
||||
|
||||
let repo = repo.reload();
|
||||
|
||||
let expected_heads = hashset! {
|
||||
repo.view().checkout().clone(),
|
||||
head_unchanged.id().clone(),
|
||||
head_add_tx1.id().clone(),
|
||||
head_add_tx2.id().clone(),
|
||||
public_head_unchanged.id().clone(),
|
||||
public_head_remove_tx1.id().clone(),
|
||||
public_head_remove_tx2.id().clone(),
|
||||
public_head_add_tx1.id().clone(),
|
||||
public_head_add_tx2.id().clone(),
|
||||
};
|
||||
assert_eq!(repo.view().heads(), &expected_heads);
|
||||
|
||||
let expected_public_heads = hashset! {
|
||||
public_head_unchanged.id().clone(),
|
||||
public_head_add_tx1.id().clone(),
|
||||
public_head_add_tx2.id().clone(),
|
||||
};
|
||||
assert_eq!(repo.view().public_heads(), &expected_public_heads);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_merge_views_checkout() {
|
||||
// Tests merging of the view's checkout (by performing concurrent operations).
|
||||
let settings = testutils::user_settings();
|
||||
let (_temp_dir, repo) = testutils::init_repo(&settings, false);
|
||||
|
||||
let mut tx1 = repo.start_transaction("test");
|
||||
let checkout_tx1 = testutils::create_random_commit(&settings, &repo)
|
||||
.set_open(false)
|
||||
.write_to_repo(tx1.mut_repo());
|
||||
tx1.mut_repo().set_checkout(checkout_tx1.id().clone());
|
||||
tx1.commit();
|
||||
|
||||
let mut tx2 = repo.start_transaction("test");
|
||||
let checkout_tx2 = testutils::create_random_commit(&settings, &repo)
|
||||
.set_open(false)
|
||||
.write_to_repo(tx2.mut_repo());
|
||||
tx2.mut_repo().set_checkout(checkout_tx2.id().clone());
|
||||
tx2.commit();
|
||||
|
||||
let repo = repo.reload();
|
||||
|
||||
// We currently arbitrarily pick the first transaction's checkout (first by
|
||||
// transaction end time).
|
||||
assert_eq!(repo.view().checkout(), checkout_tx1.id());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_merge_views_git_refs() {
|
||||
// Tests merging of git refs (by performing concurrent operations). See
|
||||
// test_refs.rs for tests of merging of individual ref targets.
|
||||
let settings = testutils::user_settings();
|
||||
let (_temp_dir, repo) = testutils::init_repo(&settings, false);
|
||||
|
||||
let mut tx = repo.start_transaction("test");
|
||||
let mut_repo = tx.mut_repo();
|
||||
let main_branch_tx0 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
mut_repo.set_git_ref(
|
||||
"refs/heads/main".to_string(),
|
||||
RefTarget::Normal(main_branch_tx0.id().clone()),
|
||||
);
|
||||
let feature_branch_tx0 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
mut_repo.set_git_ref(
|
||||
"refs/heads/feature".to_string(),
|
||||
RefTarget::Normal(feature_branch_tx0.id().clone()),
|
||||
);
|
||||
let repo = tx.commit();
|
||||
|
||||
let mut tx1 = repo.start_transaction("test");
|
||||
let main_branch_tx1 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(tx1.mut_repo());
|
||||
tx1.mut_repo().set_git_ref(
|
||||
"refs/heads/main".to_string(),
|
||||
RefTarget::Normal(main_branch_tx1.id().clone()),
|
||||
);
|
||||
let feature_branch_tx1 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(tx1.mut_repo());
|
||||
tx1.mut_repo().set_git_ref(
|
||||
"refs/heads/feature".to_string(),
|
||||
RefTarget::Normal(feature_branch_tx1.id().clone()),
|
||||
);
|
||||
tx1.commit();
|
||||
|
||||
let mut tx2 = repo.start_transaction("test");
|
||||
let main_branch_tx2 =
|
||||
testutils::create_random_commit(&settings, &repo).write_to_repo(tx2.mut_repo());
|
||||
tx2.mut_repo().set_git_ref(
|
||||
"refs/heads/main".to_string(),
|
||||
RefTarget::Normal(main_branch_tx2.id().clone()),
|
||||
);
|
||||
tx2.commit();
|
||||
|
||||
let repo = repo.reload();
|
||||
let expected_main_branch = RefTarget::Conflict {
|
||||
removes: vec![main_branch_tx0.id().clone()],
|
||||
adds: vec![main_branch_tx1.id().clone(), main_branch_tx2.id().clone()],
|
||||
};
|
||||
let expected_feature_branch = RefTarget::Normal(feature_branch_tx1.id().clone());
|
||||
assert_eq!(
|
||||
repo.view().git_refs(),
|
||||
&btreemap! {
|
||||
"refs/heads/main".to_string() => expected_main_branch,
|
||||
"refs/heads/feature".to_string() => expected_feature_branch,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue