20260716 增加verification-only缓存正确性复核
This commit is contained in:
@@ -2276,3 +2276,121 @@ fn pack_file_can_lazy_load_bytes_from_external_repo_bytes_store() {
|
||||
assert_eq!(file.bytes_cloned().expect("cloned repo bytes"), bytes);
|
||||
assert_eq!(file.compute_sha256().expect("compute sha256"), file.sha256);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_only_checkpoint_isolated_from_source_work_db() {
|
||||
let td = tempfile::tempdir().expect("tempdir");
|
||||
let source_path = td.path().join("source-work-db");
|
||||
let checkpoint_path = td.path().join("checkpoint-work-db");
|
||||
let uri = "rsync://example.test/repo/a.roa";
|
||||
let bytes = b"checkpoint-object";
|
||||
let hash = sha256_hex(bytes);
|
||||
{
|
||||
let source = RocksStore::open(&source_path).expect("open source");
|
||||
source
|
||||
.put_blob_bytes_batch(&[(hash.clone(), bytes.to_vec())])
|
||||
.expect("put blob");
|
||||
source
|
||||
.put_repository_view_entry(&RepositoryViewEntry {
|
||||
rsync_uri: uri.to_string(),
|
||||
current_hash: Some(hash),
|
||||
repository_source: Some("fixture".to_string()),
|
||||
object_type: Some("roa".to_string()),
|
||||
state: RepositoryViewState::Present,
|
||||
})
|
||||
.expect("put view");
|
||||
}
|
||||
|
||||
RocksStore::create_read_only_checkpoint(&source_path, &checkpoint_path)
|
||||
.expect("create checkpoint");
|
||||
let checkpoint = RocksStore::open(&checkpoint_path).expect("open checkpoint");
|
||||
checkpoint
|
||||
.delete_repository_view_entry(uri)
|
||||
.expect("delete checkpoint entry");
|
||||
drop(checkpoint);
|
||||
|
||||
let source = RocksStore::open(&source_path).expect("reopen source");
|
||||
assert!(
|
||||
source
|
||||
.get_repository_view_entry(uri)
|
||||
.expect("get source entry")
|
||||
.is_some()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_only_external_repo_bytes_rejects_writes() {
|
||||
let td = tempfile::tempdir().expect("tempdir");
|
||||
let path = td.path().join("repo-bytes.db");
|
||||
let hash = sha256_hex(b"repo-object");
|
||||
{
|
||||
let writable = ExternalRepoBytesDb::open(&path).expect("open writable repo bytes");
|
||||
writable
|
||||
.put_blob_bytes_batch(&[(hash.clone(), b"repo-object".to_vec())])
|
||||
.expect("seed repo bytes");
|
||||
}
|
||||
let read_only = ExternalRepoBytesDb::open_read_only(&path).expect("open read-only repo bytes");
|
||||
assert_eq!(
|
||||
read_only
|
||||
.get_blob_bytes(&hash)
|
||||
.expect("read repo bytes")
|
||||
.expect("blob"),
|
||||
b"repo-object"
|
||||
);
|
||||
assert!(
|
||||
read_only
|
||||
.put_blob_bytes_batch(&[(hash, b"repo-object".to_vec())])
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_only_store_accepts_only_idempotent_existing_blob_apply() {
|
||||
let td = tempfile::tempdir().expect("tempdir");
|
||||
let work_db_path = td.path().join("work-db");
|
||||
let repo_bytes_path = td.path().join("repo-bytes.db");
|
||||
let bytes = b"repo-object".to_vec();
|
||||
let hash = sha256_hex(&bytes);
|
||||
{
|
||||
let repo_bytes = ExternalRepoBytesDb::open(&repo_bytes_path).expect("open repo bytes");
|
||||
repo_bytes
|
||||
.put_blob_bytes_batch(&[(hash.clone(), bytes.clone())])
|
||||
.expect("seed repo bytes");
|
||||
}
|
||||
let store =
|
||||
RocksStore::open_with_external_repo_bytes_read_only(&work_db_path, &repo_bytes_path)
|
||||
.expect("open read-only store");
|
||||
store
|
||||
.put_blob_bytes_batch(&[(hash.clone(), bytes)])
|
||||
.expect("idempotent apply");
|
||||
assert!(
|
||||
store
|
||||
.put_blob_bytes_batch(&[(hash, b"different".to_vec())])
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repository_blob_verification_detects_missing_external_blob() {
|
||||
let td = tempfile::tempdir().expect("tempdir");
|
||||
let repo_bytes_path = td.path().join("repo-bytes.db");
|
||||
ExternalRepoBytesDb::open(&repo_bytes_path).expect("create repo bytes");
|
||||
let store = RocksStore::open_with_external_repo_bytes_read_only(
|
||||
&td.path().join("work-db"),
|
||||
&repo_bytes_path,
|
||||
)
|
||||
.expect("open work db");
|
||||
store
|
||||
.put_repository_view_entry(&RepositoryViewEntry {
|
||||
rsync_uri: "rsync://example.test/repo/missing.roa".to_string(),
|
||||
current_hash: Some(sha256_hex(b"missing")),
|
||||
repository_source: Some("fixture".to_string()),
|
||||
object_type: Some("roa".to_string()),
|
||||
state: RepositoryViewState::Present,
|
||||
})
|
||||
.expect("put view");
|
||||
let error = store
|
||||
.verify_current_repository_blobs(16)
|
||||
.expect_err("missing blob must fail");
|
||||
assert!(error.to_string().contains("missing.roa"), "{error}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user