
https://github.com/user-attachments/assets/78db908e-cfe5-4803-b0dc-4f33bc457840 * starts to extract usernames out of `users/` GitHub API responses, and pass those along with e-mails in the collab sessions as part of the `User` data * adjusts various prefill and seed test methods so that the new data can be retrieved from GitHub properly * if there's an active call, where guests have write permissions and e-mails, allow to trigger `FillCoAuthors` action in the context of the git panel, that will fill in `co-authored-by:` lines, using e-mail and names (or GitHub handle names if name is absent) * the action tries to not duplicate such entries, if any are present already, and adds those below the rest of the commit input's text Concerns: * users with write permissions and no e-mails will be silently omitted — adding odd entries that try to indicate this or raising pop-ups is very intrusive (maybe, we can add `#`-prefixed comments?), logging seems pointless * it's not clear whether the data prefill will run properly on the existing users — seems tolerable now, as it seems that we get e-mails properly already, so we'll see GitHub handles instead of names in the worst case. This can be prefilled better later. * e-mails and names for a particular project may be not what the user wants. E.g. my `.gitconfig` has ``` [user] email = mail4score@gmail.com # .....snip [includeif "gitdir:**/work/zed/**/.git"] path = ~/.gitconfig.work ``` and that one has ``` [user] email = kirill@zed.dev ``` while my GitHub profile is configured so, that `mail4score@gmail.com` is the public, commit e-mail. So, when I'm a participant in a Zed session, wrong e-mail will be picked. The problem is, it's impossible for a host to get remote's collaborator git metadata for a particular project, as that might not even exist on disk for the client. Seems that we might want to add some "project git URL <-> user name and email" mapping in the settings(?). The design of this is not very clear, so the PR concentrates on the basics for now. When https://github.com/zed-industries/zed/pull/23308 lands, most of the issues can be solved by collaborators manually, before committing. Release Notes: - N/A
198 lines
5.8 KiB
Rust
198 lines
5.8 KiB
Rust
mod billing_subscription_tests;
|
|
mod buffer_tests;
|
|
mod channel_tests;
|
|
mod contributor_tests;
|
|
mod db_tests;
|
|
// we only run postgres tests on macos right now
|
|
#[cfg(target_os = "macos")]
|
|
mod embedding_tests;
|
|
mod extension_tests;
|
|
mod feature_flag_tests;
|
|
mod message_tests;
|
|
mod processed_stripe_event_tests;
|
|
mod user_tests;
|
|
|
|
use crate::migrations::run_database_migrations;
|
|
|
|
use super::*;
|
|
use gpui::BackgroundExecutor;
|
|
use parking_lot::Mutex;
|
|
use sea_orm::ConnectionTrait;
|
|
use sqlx::migrate::MigrateDatabase;
|
|
use std::sync::{
|
|
atomic::{AtomicI32, AtomicU32, Ordering::SeqCst},
|
|
Arc,
|
|
};
|
|
|
|
pub struct TestDb {
|
|
pub db: Option<Arc<Database>>,
|
|
pub connection: Option<sqlx::AnyConnection>,
|
|
}
|
|
|
|
impl TestDb {
|
|
pub fn sqlite(background: BackgroundExecutor) -> Self {
|
|
let url = "sqlite::memory:";
|
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_io()
|
|
.enable_time()
|
|
.build()
|
|
.unwrap();
|
|
|
|
let mut db = runtime.block_on(async {
|
|
let mut options = ConnectOptions::new(url);
|
|
options.max_connections(5);
|
|
let mut db = Database::new(options, Executor::Deterministic(background))
|
|
.await
|
|
.unwrap();
|
|
let sql = include_str!(concat!(
|
|
env!("CARGO_MANIFEST_DIR"),
|
|
"/migrations.sqlite/20221109000000_test_schema.sql"
|
|
));
|
|
db.pool
|
|
.execute(sea_orm::Statement::from_string(
|
|
db.pool.get_database_backend(),
|
|
sql,
|
|
))
|
|
.await
|
|
.unwrap();
|
|
db.initialize_notification_kinds().await.unwrap();
|
|
db
|
|
});
|
|
|
|
db.runtime = Some(runtime);
|
|
|
|
Self {
|
|
db: Some(Arc::new(db)),
|
|
connection: None,
|
|
}
|
|
}
|
|
|
|
pub fn postgres(background: BackgroundExecutor) -> Self {
|
|
static LOCK: Mutex<()> = Mutex::new(());
|
|
|
|
let _guard = LOCK.lock();
|
|
let mut rng = StdRng::from_entropy();
|
|
let url = format!(
|
|
"postgres://postgres@localhost/zed-test-{}",
|
|
rng.gen::<u128>()
|
|
);
|
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_io()
|
|
.enable_time()
|
|
.build()
|
|
.unwrap();
|
|
|
|
let mut db = runtime.block_on(async {
|
|
sqlx::Postgres::create_database(&url)
|
|
.await
|
|
.expect("failed to create test db");
|
|
let mut options = ConnectOptions::new(url);
|
|
options
|
|
.max_connections(5)
|
|
.idle_timeout(Duration::from_secs(0));
|
|
let mut db = Database::new(options, Executor::Deterministic(background))
|
|
.await
|
|
.unwrap();
|
|
let migrations_path = concat!(env!("CARGO_MANIFEST_DIR"), "/migrations");
|
|
run_database_migrations(db.options(), migrations_path)
|
|
.await
|
|
.unwrap();
|
|
db.initialize_notification_kinds().await.unwrap();
|
|
db
|
|
});
|
|
|
|
db.runtime = Some(runtime);
|
|
|
|
Self {
|
|
db: Some(Arc::new(db)),
|
|
connection: None,
|
|
}
|
|
}
|
|
|
|
pub fn db(&self) -> &Arc<Database> {
|
|
self.db.as_ref().unwrap()
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! test_both_dbs {
|
|
($test_name:ident, $postgres_test_name:ident, $sqlite_test_name:ident) => {
|
|
#[cfg(target_os = "macos")]
|
|
#[gpui::test]
|
|
async fn $postgres_test_name(cx: &mut gpui::TestAppContext) {
|
|
let test_db = $crate::db::TestDb::postgres(cx.executor().clone());
|
|
$test_name(test_db.db()).await;
|
|
}
|
|
|
|
#[gpui::test]
|
|
async fn $sqlite_test_name(cx: &mut gpui::TestAppContext) {
|
|
let test_db = $crate::db::TestDb::sqlite(cx.executor().clone());
|
|
$test_name(test_db.db()).await;
|
|
}
|
|
};
|
|
}
|
|
|
|
impl Drop for TestDb {
|
|
fn drop(&mut self) {
|
|
let db = self.db.take().unwrap();
|
|
if let sea_orm::DatabaseBackend::Postgres = db.pool.get_database_backend() {
|
|
db.runtime.as_ref().unwrap().block_on(async {
|
|
use util::ResultExt;
|
|
let query = "
|
|
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
|
FROM pg_stat_activity
|
|
WHERE
|
|
pg_stat_activity.datname = current_database() AND
|
|
pid <> pg_backend_pid();
|
|
";
|
|
db.pool
|
|
.execute(sea_orm::Statement::from_string(
|
|
db.pool.get_database_backend(),
|
|
query,
|
|
))
|
|
.await
|
|
.log_err();
|
|
sqlx::Postgres::drop_database(db.options.get_url())
|
|
.await
|
|
.log_err();
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
fn channel_tree(channels: &[(ChannelId, &[ChannelId], &'static str)]) -> Vec<Channel> {
|
|
channels
|
|
.iter()
|
|
.map(|(id, parent_path, name)| Channel {
|
|
id: *id,
|
|
name: name.to_string(),
|
|
visibility: ChannelVisibility::Members,
|
|
parent_path: parent_path.to_vec(),
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
static GITHUB_USER_ID: AtomicI32 = AtomicI32::new(5);
|
|
|
|
async fn new_test_user(db: &Arc<Database>, email: &str) -> UserId {
|
|
db.create_user(
|
|
email,
|
|
None,
|
|
false,
|
|
NewUserParams {
|
|
github_login: email[0..email.find('@').unwrap()].to_string(),
|
|
github_user_id: GITHUB_USER_ID.fetch_add(1, SeqCst),
|
|
},
|
|
)
|
|
.await
|
|
.unwrap()
|
|
.user_id
|
|
}
|
|
|
|
static TEST_CONNECTION_ID: AtomicU32 = AtomicU32::new(1);
|
|
fn new_test_connection(server: ServerId) -> ConnectionId {
|
|
ConnectionId {
|
|
id: TEST_CONNECTION_ID.fetch_add(1, SeqCst),
|
|
owner_id: server.0 as u32,
|
|
}
|
|
}
|