Add buffer integration test
Rearrange channel crate structure Get channel buffer from database co-authored-by: Max <max@zed.dev>
This commit is contained in:
parent
ff5035ea37
commit
a7a4e2e369
33 changed files with 403 additions and 39 deletions
|
@ -1,7 +1,8 @@
|
|||
#[cfg(test)]
|
||||
mod db_tests;
|
||||
pub mod tests;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_db;
|
||||
pub use tests::TestDb;
|
||||
|
||||
mod ids;
|
||||
mod queries;
|
||||
|
|
|
@ -9,6 +9,3 @@ pub mod rooms;
|
|||
pub mod servers;
|
||||
pub mod signups;
|
||||
pub mod users;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod buffer_tests;
|
||||
|
|
|
@ -689,6 +689,34 @@ impl Database {
|
|||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_or_create_buffer_for_channel(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
) -> Result<BufferId> {
|
||||
self.transaction(|tx| async move {
|
||||
let tx = tx;
|
||||
let channel = channel::Entity::find_by_id(channel_id)
|
||||
.one(&*tx)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("invalid channel"))?;
|
||||
|
||||
if let Some(id) = channel.main_buffer_id {
|
||||
return Ok(id);
|
||||
} else {
|
||||
let buffer = buffer::ActiveModel::new().insert(&*tx).await?;
|
||||
channel::ActiveModel {
|
||||
id: ActiveValue::Unchanged(channel_id),
|
||||
main_buffer_id: ActiveValue::Set(Some(buffer.id)),
|
||||
..Default::default()
|
||||
}
|
||||
.update(&*tx)
|
||||
.await?;
|
||||
Ok(buffer.id)
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::db::ChannelId;
|
||||
use crate::db::{BufferId, ChannelId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
|
||||
|
@ -7,6 +7,7 @@ pub struct Model {
|
|||
#[sea_orm(primary_key)]
|
||||
pub id: ChannelId,
|
||||
pub name: String,
|
||||
pub main_buffer_id: Option<BufferId>,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
mod buffer_tests;
|
||||
mod db_tests;
|
||||
|
||||
use super::*;
|
||||
use gpui::executor::Background;
|
||||
use parking_lot::Mutex;
|
||||
|
@ -96,7 +99,7 @@ macro_rules! test_both_dbs {
|
|||
($test_name:ident, $postgres_test_name:ident, $sqlite_test_name:ident) => {
|
||||
#[gpui::test]
|
||||
async fn $postgres_test_name() {
|
||||
let test_db = crate::db::test_db::TestDb::postgres(
|
||||
let test_db = crate::db::TestDb::postgres(
|
||||
gpui::executor::Deterministic::new(0).build_background(),
|
||||
);
|
||||
$test_name(test_db.db()).await;
|
||||
|
@ -104,9 +107,8 @@ macro_rules! test_both_dbs {
|
|||
|
||||
#[gpui::test]
|
||||
async fn $sqlite_test_name() {
|
||||
let test_db = crate::db::test_db::TestDb::sqlite(
|
||||
gpui::executor::Deterministic::new(0).build_background(),
|
||||
);
|
||||
let test_db =
|
||||
crate::db::TestDb::sqlite(gpui::executor::Deterministic::new(0).build_background());
|
||||
$test_name(test_db.db()).await;
|
||||
}
|
||||
};
|
|
@ -3,7 +3,7 @@ use crate::test_both_dbs;
|
|||
use gpui::executor::{Background, Deterministic};
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
use std::sync::Arc;
|
||||
use test_db::TestDb;
|
||||
use tests::TestDb;
|
||||
|
||||
test_both_dbs!(
|
||||
test_get_users,
|
||||
|
@ -1329,6 +1329,35 @@ async fn test_channel_renames(db: &Arc<Database>) {
|
|||
assert!(bad_name_rename.is_err())
|
||||
}
|
||||
|
||||
test_both_dbs!(
|
||||
test_get_or_create_channel_buffer,
|
||||
test_get_or_create_channel_buffer_postgres,
|
||||
test_get_or_create_channel_buffer_sqlite
|
||||
);
|
||||
|
||||
async fn test_get_or_create_channel_buffer(db: &Arc<Database>) {
|
||||
let a_id = db
|
||||
.create_user(
|
||||
"user1@example.com",
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user1".into(),
|
||||
github_user_id: 5,
|
||||
invite_count: 0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.user_id;
|
||||
|
||||
let zed_id = db.create_root_channel("zed", "1", a_id).await.unwrap();
|
||||
|
||||
let first_buffer_id = db.get_or_create_buffer_for_channel(zed_id).await.unwrap();
|
||||
let second_buffer_id = db.get_or_create_buffer_for_channel(zed_id).await.unwrap();
|
||||
|
||||
assert_eq!(first_buffer_id, second_buffer_id);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_multiple_signup_overwrite() {
|
||||
let test_db = TestDb::postgres(build_background_executor());
|
|
@ -35,8 +35,8 @@ use lazy_static::lazy_static;
|
|||
use prometheus::{register_int_gauge, IntGauge};
|
||||
use rpc::{
|
||||
proto::{
|
||||
self, AnyTypedEnvelope, EntityMessage, EnvelopedMessage, LiveKitConnectionInfo,
|
||||
RequestMessage,
|
||||
self, AnyTypedEnvelope, EntityMessage, EnvelopedMessage, GetChannelBufferResponse,
|
||||
LiveKitConnectionInfo, RequestMessage,
|
||||
},
|
||||
Connection, ConnectionId, Peer, Receipt, TypedEnvelope,
|
||||
};
|
||||
|
@ -248,6 +248,7 @@ impl Server {
|
|||
.add_request_handler(remove_channel_member)
|
||||
.add_request_handler(set_channel_member_admin)
|
||||
.add_request_handler(rename_channel)
|
||||
.add_request_handler(get_channel_buffer)
|
||||
.add_request_handler(get_channel_members)
|
||||
.add_request_handler(respond_to_channel_invite)
|
||||
.add_request_handler(join_channel)
|
||||
|
@ -2478,6 +2479,26 @@ async fn join_channel(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_channel_buffer(
|
||||
request: proto::GetChannelBuffer,
|
||||
response: Response<proto::GetChannelBuffer>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
let db = session.db().await;
|
||||
let channel_id = ChannelId::from_proto(request.channel_id);
|
||||
|
||||
let buffer_id = db.get_or_create_buffer_for_channel(channel_id).await?;
|
||||
|
||||
let buffer = db.get_buffer(buffer_id).await?;
|
||||
|
||||
response.send(GetChannelBufferResponse {
|
||||
base_text: buffer.base_text,
|
||||
operations: buffer.operations,
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_diff_base(request: proto::UpdateDiffBase, session: Session) -> Result<()> {
|
||||
let project_id = ProjectId::from_proto(request.project_id);
|
||||
let project_connection_ids = session
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::{
|
||||
db::{test_db::TestDb, NewUserParams, UserId},
|
||||
db::{tests::TestDb, NewUserParams, UserId},
|
||||
executor::Executor,
|
||||
rpc::{Server, CLEANUP_TIMEOUT},
|
||||
AppState,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use call::{ActiveCall, Room};
|
||||
use channel::ChannelStore;
|
||||
use client::{
|
||||
self, proto::PeerId, ChannelStore, Client, Connection, Credentials, EstablishConnectionError,
|
||||
UserStore,
|
||||
self, proto::PeerId, Client, Connection, Credentials, EstablishConnectionError, UserStore,
|
||||
};
|
||||
use collections::{HashMap, HashSet};
|
||||
use fs::FakeFs;
|
||||
|
@ -31,6 +31,7 @@ use std::{
|
|||
use util::http::FakeHttpClient;
|
||||
use workspace::Workspace;
|
||||
|
||||
mod channel_buffer_tests;
|
||||
mod channel_tests;
|
||||
mod integration_tests;
|
||||
mod randomized_integration_tests;
|
||||
|
|
84
crates/collab/src/tests/channel_buffer_tests.rs
Normal file
84
crates/collab/src/tests/channel_buffer_tests.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
use crate::tests::TestServer;
|
||||
|
||||
use channel::channel_buffer::ChannelBuffer;
|
||||
use gpui::{executor::Deterministic, ModelHandle, TestAppContext};
|
||||
use std::{ops::Range, sync::Arc};
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_channel_buffers(
|
||||
deterministic: Arc<Deterministic>,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
let zed_id = server
|
||||
.make_channel("zed", (&client_a, cx_a), &mut [(&client_b, cx_b)])
|
||||
.await;
|
||||
|
||||
let a_document =
|
||||
cx_a.add_model(|cx| ChannelBuffer::for_channel(zed_id, client_a.client().to_owned(), cx));
|
||||
let channel_buffer_a = a_document
|
||||
.update(cx_a, |doc, cx| doc.buffer(cx))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
edit_channel_buffer(&channel_buffer_a, cx_a, [(0..0, "hello world")]);
|
||||
edit_channel_buffer(&channel_buffer_a, cx_a, [(5..5, ", cruel")]);
|
||||
edit_channel_buffer(&channel_buffer_a, cx_a, [(0..5, "goodbye")]);
|
||||
undo_channel_buffer(&channel_buffer_a, cx_a);
|
||||
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_a, cx_a),
|
||||
"hello, cruel world"
|
||||
);
|
||||
|
||||
let b_document =
|
||||
cx_b.add_model(|cx| ChannelBuffer::for_channel(zed_id, client_b.client().to_owned(), cx));
|
||||
let channel_buffer_b = b_document
|
||||
.update(cx_b, |doc, cx| doc.buffer(cx))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_b, cx_b),
|
||||
"hello, cruel world"
|
||||
);
|
||||
|
||||
edit_channel_buffer(&channel_buffer_b, cx_b, [(7..12, "beautiful")]);
|
||||
|
||||
deterministic.run_until_parked();
|
||||
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_a, cx_a),
|
||||
"hello, beautiful world"
|
||||
);
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_b, cx_b),
|
||||
"hello, beautiful world"
|
||||
);
|
||||
}
|
||||
|
||||
fn edit_channel_buffer<I>(
|
||||
channel_buffer: &ModelHandle<language::Buffer>,
|
||||
cx: &mut TestAppContext,
|
||||
edits: I,
|
||||
) where
|
||||
I: IntoIterator<Item = (Range<usize>, &'static str)>,
|
||||
{
|
||||
channel_buffer.update(cx, |buffer, cx| buffer.edit(edits, None, cx));
|
||||
}
|
||||
|
||||
fn undo_channel_buffer(channel_buffer: &ModelHandle<language::Buffer>, cx: &mut TestAppContext) {
|
||||
channel_buffer.update(cx, |buffer, cx| buffer.undo(cx));
|
||||
}
|
||||
|
||||
fn channel_buffer_text(
|
||||
channel_buffer: &ModelHandle<language::Buffer>,
|
||||
cx: &mut TestAppContext,
|
||||
) -> String {
|
||||
channel_buffer.read_with(cx, |buffer, _| buffer.text())
|
||||
}
|
|
@ -3,7 +3,8 @@ use crate::{
|
|||
tests::{room_participants, RoomParticipants, TestServer},
|
||||
};
|
||||
use call::ActiveCall;
|
||||
use client::{ChannelId, ChannelMembership, ChannelStore, User};
|
||||
use channel::{ChannelId, ChannelMembership, ChannelStore};
|
||||
use client::User;
|
||||
use gpui::{executor::Deterministic, ModelHandle, TestAppContext};
|
||||
use rpc::{proto, RECEIVE_TIMEOUT};
|
||||
use std::sync::Arc;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue