mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 01:07:15 +03:00
f6d06a266a
Summary: `bulk_add()` method was checking for conflicts correctly i.e. it wouldn't fail if we try to insert the same mapping twice. `bulk_add_git_mapping_in_transaction` wasn't doing this check i.e. it would fail. This caused us a few problems and this diff fixes them - now `bulk_add_git_mapping_in_transaction` would do the same checks as bulk_add was doing previously. There is another important change in behaviour: if we try to insert two entries, one of them has a conflict another don't then previously we'd insert the second entry. Now we don't insert any, arguably that's a preferred behaviour. Reviewed By: krallin Differential Revision: D22332001 fbshipit-source-id: 86fff8c23c43eeca0fb36b01b10cdaa73b3ce4ab
248 lines
7.0 KiB
Rust
248 lines
7.0 KiB
Rust
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This software may be used and distributed according to the terms of the
|
|
* GNU General Public License version 2.
|
|
*/
|
|
|
|
#![deny(warnings)]
|
|
|
|
use anyhow::Error;
|
|
use assert_matches::assert_matches;
|
|
use bonsai_git_mapping::{
|
|
AddGitMappingErrorKind, BonsaiGitMapping, BonsaiGitMappingEntry, BonsaisOrGitShas,
|
|
SqlBonsaiGitMappingConnection,
|
|
};
|
|
use context::CoreContext;
|
|
use fbinit::FacebookInit;
|
|
use futures::compat::Future01CompatExt;
|
|
use mononoke_types_mocks::changesetid as bonsai;
|
|
use mononoke_types_mocks::hash::*;
|
|
use mononoke_types_mocks::repo::REPO_ZERO;
|
|
use sql::Connection;
|
|
use sql_construct::SqlConstruct;
|
|
use sql_ext::{open_sqlite_in_memory, SqlConnections};
|
|
|
|
#[fbinit::test]
|
|
async fn test_add_and_get(fb: FacebookInit) -> Result<(), Error> {
|
|
let ctx = CoreContext::test_mock(fb);
|
|
let mapping = SqlBonsaiGitMappingConnection::with_sqlite_in_memory()?.with_repo_id(REPO_ZERO);
|
|
|
|
let entry = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::ONES_CSID,
|
|
git_sha1: ONES_GIT_SHA1,
|
|
};
|
|
|
|
mapping.bulk_add(&ctx, &[entry.clone()]).await?;
|
|
|
|
let result = mapping
|
|
.get(&ctx, BonsaisOrGitShas::Bonsai(vec![bonsai::ONES_CSID]))
|
|
.await?;
|
|
assert_eq!(result, vec![entry.clone()]);
|
|
let result = mapping
|
|
.get_git_sha1_from_bonsai(&ctx, bonsai::ONES_CSID)
|
|
.await?;
|
|
assert_eq!(result, Some(ONES_GIT_SHA1));
|
|
let result = mapping
|
|
.get_bonsai_from_git_sha1(&ctx, ONES_GIT_SHA1)
|
|
.await?;
|
|
assert_eq!(result, Some(bonsai::ONES_CSID));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[fbinit::test]
|
|
async fn test_add_duplicate(fb: FacebookInit) -> Result<(), Error> {
|
|
// Inserting duplicate entries should just be a successful no-op.
|
|
let ctx = CoreContext::test_mock(fb);
|
|
let mapping = SqlBonsaiGitMappingConnection::with_sqlite_in_memory()?.with_repo_id(REPO_ZERO);
|
|
|
|
let entry = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::ONES_CSID,
|
|
git_sha1: ONES_GIT_SHA1,
|
|
};
|
|
|
|
mapping.bulk_add(&ctx, &[entry.clone()]).await?;
|
|
mapping.bulk_add(&ctx, &[entry.clone()]).await?;
|
|
|
|
let result = mapping
|
|
.get_git_sha1_from_bonsai(&ctx, bonsai::ONES_CSID)
|
|
.await?;
|
|
assert_eq!(result, Some(ONES_GIT_SHA1));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[fbinit::test]
|
|
async fn test_add_conflict(fb: FacebookInit) -> Result<(), Error> {
|
|
// Adding conflicting entries should fail. Other entries inserted in the
|
|
// same bulk_add should be inserted.
|
|
let ctx = CoreContext::test_mock(fb);
|
|
let mapping = SqlBonsaiGitMappingConnection::with_sqlite_in_memory()?.with_repo_id(REPO_ZERO);
|
|
|
|
let entry = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::ONES_CSID,
|
|
git_sha1: ONES_GIT_SHA1,
|
|
};
|
|
|
|
mapping.bulk_add(&ctx, &[entry.clone()]).await?;
|
|
|
|
let entries = vec![
|
|
BonsaiGitMappingEntry {
|
|
// This entry could be inserted normally, but it won't because we have a conflicting
|
|
// entry
|
|
bcs_id: bonsai::TWOS_CSID,
|
|
git_sha1: TWOS_GIT_SHA1,
|
|
},
|
|
BonsaiGitMappingEntry {
|
|
// Conflicting entry.
|
|
bcs_id: bonsai::ONES_CSID,
|
|
git_sha1: THREES_GIT_SHA1,
|
|
},
|
|
];
|
|
|
|
let res = mapping.bulk_add(&ctx, &entries).await;
|
|
assert_matches!(res, Err(AddGitMappingErrorKind::Conflict(_)));
|
|
|
|
let result = mapping
|
|
.get_git_sha1_from_bonsai(&ctx, bonsai::TWOS_CSID)
|
|
.await?;
|
|
assert_eq!(result, None);
|
|
|
|
let entries = vec![BonsaiGitMappingEntry {
|
|
// Now this entry will be inserted normally
|
|
bcs_id: bonsai::TWOS_CSID,
|
|
git_sha1: TWOS_GIT_SHA1,
|
|
}];
|
|
|
|
mapping.bulk_add(&ctx, &entries).await?;
|
|
let result = mapping
|
|
.get_git_sha1_from_bonsai(&ctx, bonsai::TWOS_CSID)
|
|
.await?;
|
|
assert_eq!(result, Some(TWOS_GIT_SHA1));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[fbinit::test]
|
|
async fn test_bulk_add(fb: FacebookInit) -> Result<(), Error> {
|
|
let ctx = CoreContext::test_mock(fb);
|
|
let mapping = SqlBonsaiGitMappingConnection::with_sqlite_in_memory()?.with_repo_id(REPO_ZERO);
|
|
|
|
let entry1 = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::ONES_CSID,
|
|
git_sha1: ONES_GIT_SHA1,
|
|
};
|
|
let entry2 = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::TWOS_CSID,
|
|
git_sha1: TWOS_GIT_SHA1,
|
|
};
|
|
let entry3 = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::THREES_CSID,
|
|
git_sha1: THREES_GIT_SHA1,
|
|
};
|
|
|
|
mapping
|
|
.bulk_add(&ctx, &[entry1.clone(), entry2.clone(), entry3.clone()])
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[fbinit::test]
|
|
async fn test_missing(fb: FacebookInit) -> Result<(), Error> {
|
|
let ctx = CoreContext::test_mock(fb);
|
|
let mapping = SqlBonsaiGitMappingConnection::with_sqlite_in_memory()?.with_repo_id(REPO_ZERO);
|
|
|
|
let result = mapping
|
|
.get(&ctx, BonsaisOrGitShas::Bonsai(vec![bonsai::ONES_CSID]))
|
|
.await?;
|
|
|
|
assert_eq!(result, vec![]);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[fbinit::test]
|
|
async fn test_add_with_transaction(fb: FacebookInit) -> Result<(), Error> {
|
|
let ctx = CoreContext::test_mock(fb);
|
|
let conn = open_sqlite_in_memory()?;
|
|
conn.execute_batch(SqlBonsaiGitMappingConnection::CREATION_QUERY)?;
|
|
let conn = Connection::with_sqlite(conn);
|
|
|
|
let mapping = SqlBonsaiGitMappingConnection::from_sql_connections(SqlConnections::new_single(
|
|
conn.clone(),
|
|
))
|
|
.with_repo_id(REPO_ZERO);
|
|
|
|
let entry1 = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::ONES_CSID,
|
|
git_sha1: ONES_GIT_SHA1,
|
|
};
|
|
let entry2 = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::TWOS_CSID,
|
|
git_sha1: TWOS_GIT_SHA1,
|
|
};
|
|
|
|
let txn = conn.start_transaction().compat().await?;
|
|
mapping
|
|
.bulk_add_git_mapping_in_transaction(&ctx, &[entry1.clone()], txn)
|
|
.await?
|
|
.commit()
|
|
.compat()
|
|
.await?;
|
|
|
|
assert_eq!(
|
|
Some(ONES_GIT_SHA1),
|
|
mapping
|
|
.get_git_sha1_from_bonsai(&ctx, bonsai::ONES_CSID)
|
|
.await?
|
|
);
|
|
|
|
let txn = conn.start_transaction().compat().await?;
|
|
mapping
|
|
.bulk_add_git_mapping_in_transaction(&ctx, &[entry2.clone()], txn)
|
|
.await?
|
|
.commit()
|
|
.compat()
|
|
.await?;
|
|
|
|
assert_eq!(
|
|
Some(TWOS_GIT_SHA1),
|
|
mapping
|
|
.get_git_sha1_from_bonsai(&ctx, bonsai::TWOS_CSID)
|
|
.await?
|
|
);
|
|
|
|
// Inserting duplicates fails
|
|
let txn = conn.start_transaction().compat().await?;
|
|
let res = {
|
|
let ctx = ctx.clone();
|
|
let mapping = mapping.clone();
|
|
async move {
|
|
let entry_conflict = BonsaiGitMappingEntry {
|
|
bcs_id: bonsai::TWOS_CSID,
|
|
git_sha1: THREES_GIT_SHA1,
|
|
};
|
|
mapping
|
|
.bulk_add_git_mapping_in_transaction(&ctx, &[entry_conflict], txn)
|
|
.await?
|
|
.commit()
|
|
.compat()
|
|
.await?;
|
|
Result::<_, AddGitMappingErrorKind>::Ok(())
|
|
}
|
|
}
|
|
.await;
|
|
assert_matches!(res, Err(AddGitMappingErrorKind::Conflict(_)));
|
|
|
|
assert_eq!(
|
|
Some(TWOS_GIT_SHA1),
|
|
mapping
|
|
.get_git_sha1_from_bonsai(&ctx, bonsai::TWOS_CSID)
|
|
.await?
|
|
);
|
|
|
|
Ok(())
|
|
}
|