mirror of
https://github.com/martinvonz/jj.git
synced 2024-12-27 06:27:43 +00:00
working_copy: add test of racy checkout followed by file write
We don't seem to have any tests that our protection from undetected changes caused by writes happening right after checkout, so let's add one. The test case loops 100 times and each iteration fails slightly more than 80% of the time on my machine (if I remove the protection in `TreeState::update_file_state()`), so it seems quite good at triggering the race.
This commit is contained in:
parent
e364c49854
commit
8d1cb1e1d7
1 changed files with 43 additions and 1 deletions
|
@ -16,11 +16,13 @@ use std::cmp::max;
|
|||
use std::thread;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use jj_lib::backend::TreeId;
|
||||
use jj_lib::op_store::OperationId;
|
||||
use jj_lib::repo::{Repo, StoreFactories};
|
||||
use jj_lib::repo_path::RepoPath;
|
||||
use jj_lib::working_copy::{CheckoutError, SnapshotOptions};
|
||||
use jj_lib::workspace::Workspace;
|
||||
use testutils::TestWorkspace;
|
||||
use testutils::{write_working_copy_file, TestWorkspace};
|
||||
|
||||
#[test]
|
||||
fn test_concurrent_checkout() {
|
||||
|
@ -143,3 +145,43 @@ fn test_checkout_parallel() {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_racy_checkout() {
|
||||
let settings = testutils::user_settings();
|
||||
let mut test_workspace = TestWorkspace::init(&settings, true);
|
||||
let repo = &test_workspace.repo;
|
||||
let workspace_root = test_workspace.workspace.workspace_root().clone();
|
||||
|
||||
let path = RepoPath::from_internal_string("file");
|
||||
let tree = testutils::create_tree(repo, &[(&path, "1")]);
|
||||
|
||||
fn snapshot(workspace: &mut Workspace) -> TreeId {
|
||||
let mut locked_wc = workspace.working_copy_mut().start_mutation().unwrap();
|
||||
let tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.finish(OperationId::from_hex("abc123")).unwrap();
|
||||
tree_id
|
||||
}
|
||||
|
||||
let mut num_matches = 0;
|
||||
for _ in 0..100 {
|
||||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
wc.check_out(repo.op_id().clone(), None, &tree).unwrap();
|
||||
assert_eq!(
|
||||
std::fs::read(path.to_fs_path(&workspace_root)).unwrap(),
|
||||
b"1".to_vec()
|
||||
);
|
||||
// A file written right after checkout (hopefully, from the test's perspective,
|
||||
// within the file system timestamp granularity) is detected as changed.
|
||||
write_working_copy_file(&workspace_root, &path, "x");
|
||||
let modified_tree_id = snapshot(&mut test_workspace.workspace);
|
||||
if modified_tree_id == *tree.id() {
|
||||
num_matches += 1;
|
||||
}
|
||||
// Reset the state for the next round
|
||||
write_working_copy_file(&workspace_root, &path, "1");
|
||||
}
|
||||
assert_eq!(num_matches, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue