WIP: pass synchronize channel buffers integration test
This commit is contained in:
parent
a7a4e2e369
commit
364ed1f840
15 changed files with 411 additions and 135 deletions
|
@ -189,8 +189,7 @@ CREATE INDEX "index_followers_on_room_id" ON "followers" ("room_id");
|
|||
CREATE TABLE "channels" (
|
||||
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
"name" VARCHAR NOT NULL,
|
||||
"created_at" TIMESTAMP NOT NULL DEFAULT now,
|
||||
"main_buffer_id" INTEGER REFERENCES buffers (id)
|
||||
"created_at" TIMESTAMP NOT NULL DEFAULT now
|
||||
);
|
||||
|
||||
CREATE TABLE "channel_paths" (
|
||||
|
@ -212,9 +211,12 @@ CREATE UNIQUE INDEX "index_channel_members_on_channel_id_and_user_id" ON "channe
|
|||
|
||||
CREATE TABLE "buffers" (
|
||||
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
||||
"epoch" INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE INDEX "index_buffers_on_channel_id" ON "buffers" ("channel_id");
|
||||
|
||||
CREATE TABLE "buffer_operations" (
|
||||
"buffer_id" INTEGER NOT NULL REFERENCES buffers (id) ON DELETE CASCADE,
|
||||
"epoch" INTEGER NOT NULL,
|
||||
|
@ -233,3 +235,18 @@ CREATE TABLE "buffer_snapshots" (
|
|||
"text" TEXT NOT NULL,
|
||||
PRIMARY KEY(buffer_id, epoch)
|
||||
);
|
||||
|
||||
CREATE TABLE "channel_buffer_collaborators" (
|
||||
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
"buffer_id" INTEGER NOT NULL REFERENCES buffers (id) ON DELETE CASCADE,
|
||||
"connection_id" INTEGER NOT NULL,
|
||||
"connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
|
||||
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
||||
"replica_id" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "index_channel_buffer_collaborators_on_buffer_id" ON "channel_buffer_collaborators" ("buffer_id");
|
||||
CREATE UNIQUE INDEX "index_channel_buffer_collaborators_on_buffer_id_and_replica_id" ON "channel_buffer_collaborators" ("buffer_id", "replica_id");
|
||||
CREATE INDEX "index_channel_buffer_collaborators_on_connection_server_id" ON "channel_buffer_collaborators" ("connection_server_id");
|
||||
CREATE INDEX "index_channel_buffer_collaborators_on_connection_id" ON "channel_buffer_collaborators" ("connection_id");
|
||||
CREATE UNIQUE INDEX "index_channel_buffer_collaborators_on_buffer_id_connection_id_and_server_id" ON "channel_buffer_collaborators" ("buffer_id", "connection_id", "connection_server_id");
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
CREATE TABLE "buffers" (
|
||||
"id" SERIAL PRIMARY KEY,
|
||||
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
||||
"epoch" INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE INDEX "index_buffers_on_channel_id" ON "buffers" ("channel_id");
|
||||
|
||||
CREATE TABLE "buffer_operations" (
|
||||
"buffer_id" INTEGER NOT NULL REFERENCES buffers (id) ON DELETE CASCADE,
|
||||
"epoch" INTEGER NOT NULL,
|
||||
|
@ -22,4 +25,17 @@ CREATE TABLE "buffer_snapshots" (
|
|||
PRIMARY KEY(buffer_id, epoch)
|
||||
);
|
||||
|
||||
ALTER TABLE "channels" ADD COLUMN "main_buffer_id" INTEGER REFERENCES buffers (id);
|
||||
CREATE TABLE "channel_buffer_collaborators" (
|
||||
"id" SERIAL PRIMARY KEY,
|
||||
"buffer_id" INTEGER NOT NULL REFERENCES buffers (id) ON DELETE CASCADE,
|
||||
"connection_id" INTEGER NOT NULL,
|
||||
"connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
|
||||
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
||||
"replica_id" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "index_channel_buffer_collaborators_on_buffer_id" ON "channel_buffer_collaborators" ("buffer_id");
|
||||
CREATE UNIQUE INDEX "index_channel_buffer_collaborators_on_buffer_id_and_replica_id" ON "channel_buffer_collaborators" ("buffer_id", "replica_id");
|
||||
CREATE INDEX "index_channel_buffer_collaborators_on_connection_server_id" ON "channel_buffer_collaborators" ("connection_server_id");
|
||||
CREATE INDEX "index_channel_buffer_collaborators_on_connection_id" ON "channel_buffer_collaborators" ("connection_id");
|
||||
CREATE UNIQUE INDEX "index_channel_buffer_collaborators_on_buffer_id_connection_id_and_server_id" ON "channel_buffer_collaborators" ("buffer_id", "connection_id", "connection_server_id");
|
||||
|
|
|
@ -124,3 +124,4 @@ id_type!(ReplicaId);
|
|||
id_type!(ServerId);
|
||||
id_type!(SignupId);
|
||||
id_type!(UserId);
|
||||
id_type!(ChannelBufferCollaboratorId);
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
use super::*;
|
||||
use prost::Message;
|
||||
|
||||
pub struct Buffer {
|
||||
pub struct ChannelBuffer {
|
||||
pub base_text: String,
|
||||
pub operations: Vec<proto::Operation>,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub async fn create_buffer(&self) -> Result<BufferId> {
|
||||
self.transaction(|tx| async move {
|
||||
let buffer = buffer::ActiveModel::new().insert(&*tx).await?;
|
||||
Ok(buffer.id)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn update_buffer(
|
||||
&self,
|
||||
buffer_id: BufferId,
|
||||
|
@ -69,13 +61,65 @@ impl Database {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn get_buffer(&self, id: BufferId) -> Result<Buffer> {
|
||||
pub async fn join_buffer_for_channel(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
user_id: UserId,
|
||||
connection: ConnectionId,
|
||||
) -> Result<ChannelBuffer> {
|
||||
self.transaction(|tx| async move {
|
||||
let buffer = buffer::Entity::find_by_id(id)
|
||||
.one(&*tx)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("no such buffer"))?;
|
||||
let tx = tx;
|
||||
|
||||
// Get or create buffer from channel
|
||||
self.check_user_is_channel_member(channel_id, user_id, &tx)
|
||||
.await?;
|
||||
|
||||
let buffer = channel::Model {
|
||||
id: channel_id,
|
||||
..Default::default()
|
||||
}
|
||||
.find_related(buffer::Entity)
|
||||
.one(&*tx)
|
||||
.await?;
|
||||
|
||||
let buffer = if let Some(buffer) = buffer {
|
||||
buffer
|
||||
} else {
|
||||
let buffer = buffer::ActiveModel {
|
||||
channel_id: ActiveValue::Set(channel_id),
|
||||
..Default::default()
|
||||
}
|
||||
.insert(&*tx)
|
||||
.await?;
|
||||
buffer
|
||||
};
|
||||
|
||||
// Join the collaborators
|
||||
let collaborators = buffer
|
||||
.find_related(channel_buffer_collaborator::Entity)
|
||||
.all(&*tx)
|
||||
.await?;
|
||||
let replica_ids = collaborators
|
||||
.iter()
|
||||
.map(|c| c.replica_id)
|
||||
.collect::<HashSet<_>>();
|
||||
let mut replica_id = ReplicaId(0);
|
||||
while replica_ids.contains(&replica_id) {
|
||||
replica_id.0 += 1;
|
||||
}
|
||||
channel_buffer_collaborator::ActiveModel {
|
||||
buffer_id: ActiveValue::Set(buffer.id),
|
||||
connection_id: ActiveValue::Set(connection.id as i32),
|
||||
connection_server_id: ActiveValue::Set(ServerId(connection.owner_id as i32)),
|
||||
user_id: ActiveValue::Set(user_id),
|
||||
replica_id: ActiveValue::Set(replica_id),
|
||||
..Default::default()
|
||||
}
|
||||
.insert(&*tx)
|
||||
.await?;
|
||||
|
||||
// Assemble the buffer state
|
||||
let id = buffer.id;
|
||||
let base_text = if buffer.epoch > 0 {
|
||||
buffer_snapshot::Entity::find()
|
||||
.filter(
|
||||
|
@ -128,13 +172,44 @@ impl Database {
|
|||
})
|
||||
}
|
||||
|
||||
Ok(Buffer {
|
||||
Ok(ChannelBuffer {
|
||||
base_text,
|
||||
operations,
|
||||
})
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_buffer_collaborators(&self, buffer: BufferId) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn leave_buffer(&self, buffer: BufferId, user: UserId) -> Result<()> {
|
||||
self.transaction(|tx| async move {
|
||||
//TODO
|
||||
// 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)
|
||||
// }
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
mod storage {
|
||||
|
|
|
@ -689,34 +689,6 @@ 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)]
|
||||
|
|
|
@ -3,6 +3,7 @@ pub mod buffer;
|
|||
pub mod buffer_operation;
|
||||
pub mod buffer_snapshot;
|
||||
pub mod channel;
|
||||
pub mod channel_buffer_collaborator;
|
||||
pub mod channel_member;
|
||||
pub mod channel_path;
|
||||
pub mod contact;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::db::BufferId;
|
||||
use crate::db::{BufferId, ChannelId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
||||
|
@ -7,6 +7,7 @@ pub struct Model {
|
|||
#[sea_orm(primary_key)]
|
||||
pub id: BufferId,
|
||||
pub epoch: i32,
|
||||
pub channel_id: ChannelId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
|
@ -15,6 +16,14 @@ pub enum Relation {
|
|||
Operations,
|
||||
#[sea_orm(has_many = "super::buffer_snapshot::Entity")]
|
||||
Snapshots,
|
||||
#[sea_orm(
|
||||
belongs_to = "super::channel::Entity",
|
||||
from = "Column::ChannelId",
|
||||
to = "super::channel::Column::Id"
|
||||
)]
|
||||
Channel,
|
||||
#[sea_orm(has_many = "super::channel_buffer_collaborator::Entity")]
|
||||
Collaborators,
|
||||
}
|
||||
|
||||
impl Related<super::buffer_operation::Entity> for Entity {
|
||||
|
@ -29,4 +38,16 @@ impl Related<super::buffer_snapshot::Entity> for Entity {
|
|||
}
|
||||
}
|
||||
|
||||
impl Related<super::channel::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Channel.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::channel_buffer_collaborator::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Collaborators.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
|
|
@ -7,7 +7,6 @@ pub struct Model {
|
|||
#[sea_orm(primary_key)]
|
||||
pub id: ChannelId,
|
||||
pub name: String,
|
||||
pub main_buffer_id: Option<BufferId>,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
@ -16,6 +15,8 @@ impl ActiveModelBehavior for ActiveModel {}
|
|||
pub enum Relation {
|
||||
#[sea_orm(has_one = "super::room::Entity")]
|
||||
Room,
|
||||
#[sea_orm(has_one = "super::room::Entity")]
|
||||
Buffer,
|
||||
#[sea_orm(has_many = "super::channel_member::Entity")]
|
||||
Member,
|
||||
}
|
||||
|
@ -31,3 +32,9 @@ impl Related<super::room::Entity> for Entity {
|
|||
Relation::Room.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::buffer::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Buffer.def()
|
||||
}
|
||||
}
|
||||
|
|
42
crates/collab/src/db/tables/channel_buffer_collaborator.rs
Normal file
42
crates/collab/src/db/tables/channel_buffer_collaborator.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use crate::db::{BufferId, ChannelBufferCollaboratorId, ReplicaId, ServerId, UserId};
|
||||
use rpc::ConnectionId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
||||
#[sea_orm(table_name = "channel_buffer_collaborators")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: ChannelBufferCollaboratorId,
|
||||
pub buffer_id: BufferId,
|
||||
pub connection_id: i32,
|
||||
pub connection_server_id: ServerId,
|
||||
pub user_id: UserId,
|
||||
pub replica_id: ReplicaId,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
pub fn connection(&self) -> ConnectionId {
|
||||
ConnectionId {
|
||||
owner_id: self.connection_server_id.0 as u32,
|
||||
id: self.connection_id as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(
|
||||
belongs_to = "super::buffer::Entity",
|
||||
from = "Column::BufferId",
|
||||
to = "super::buffer::Column::Id"
|
||||
)]
|
||||
Buffer,
|
||||
}
|
||||
|
||||
impl Related<super::buffer::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Buffer.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -6,7 +6,60 @@ use text::Buffer;
|
|||
test_both_dbs!(test_buffers, test_buffers_postgres, test_buffers_sqlite);
|
||||
|
||||
async fn test_buffers(db: &Arc<Database>) {
|
||||
let buffer_id = db.create_buffer().await.unwrap();
|
||||
// Prep database test info
|
||||
let a_id = db
|
||||
.create_user(
|
||||
"user_a@example.com",
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_a".into(),
|
||||
github_user_id: 101,
|
||||
invite_count: 0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.user_id;
|
||||
let b_id = db
|
||||
.create_user(
|
||||
"user_b@example.com",
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_b".into(),
|
||||
github_user_id: 102,
|
||||
invite_count: 0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.user_id;
|
||||
// This user will not be a part of the channel
|
||||
let c_id = db
|
||||
.create_user(
|
||||
"user_b@example.com",
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_b".into(),
|
||||
github_user_id: 102,
|
||||
invite_count: 0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.user_id;
|
||||
|
||||
let zed_id = db.create_root_channel("zed", "1", a_id).await.unwrap();
|
||||
|
||||
db.invite_channel_member(zed_id, b_id, a_id, false)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
db.respond_to_channel_invite(zed_id, b_id, true)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// TODO: Join buffer
|
||||
let buffer_id = db.get_or_create_buffer_for_channel(zed_id);
|
||||
|
||||
let mut buffer = Buffer::new(0, 0, "".to_string());
|
||||
let mut operations = Vec::new();
|
||||
|
@ -23,7 +76,7 @@ async fn test_buffers(db: &Arc<Database>) {
|
|||
|
||||
db.update_buffer(buffer_id, &operations).await.unwrap();
|
||||
|
||||
let buffer_data = db.get_buffer(buffer_id).await.unwrap();
|
||||
let buffer_data = db.open_buffer(buffer_id).await.unwrap();
|
||||
|
||||
let mut buffer_2 = Buffer::new(0, 0, buffer_data.base_text);
|
||||
buffer_2
|
||||
|
|
|
@ -2,7 +2,10 @@ mod connection_pool;
|
|||
|
||||
use crate::{
|
||||
auth,
|
||||
db::{self, ChannelId, ChannelsForUser, Database, ProjectId, RoomId, ServerId, User, UserId},
|
||||
db::{
|
||||
self, BufferId, ChannelId, ChannelsForUser, Database, ProjectId, RoomId, ServerId, User,
|
||||
UserId,
|
||||
},
|
||||
executor::Executor,
|
||||
AppState, Result,
|
||||
};
|
||||
|
@ -35,8 +38,8 @@ use lazy_static::lazy_static;
|
|||
use prometheus::{register_int_gauge, IntGauge};
|
||||
use rpc::{
|
||||
proto::{
|
||||
self, AnyTypedEnvelope, EntityMessage, EnvelopedMessage, GetChannelBufferResponse,
|
||||
LiveKitConnectionInfo, RequestMessage,
|
||||
self, Ack, AnyTypedEnvelope, EntityMessage, EnvelopedMessage, LiveKitConnectionInfo,
|
||||
OpenChannelBufferResponse, RequestMessage,
|
||||
},
|
||||
Connection, ConnectionId, Peer, Receipt, TypedEnvelope,
|
||||
};
|
||||
|
@ -248,7 +251,9 @@ 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(open_channel_buffer)
|
||||
.add_request_handler(close_channel_buffer)
|
||||
.add_message_handler(update_channel_buffer)
|
||||
.add_request_handler(get_channel_members)
|
||||
.add_request_handler(respond_to_channel_invite)
|
||||
.add_request_handler(join_channel)
|
||||
|
@ -2479,9 +2484,9 @@ async fn join_channel(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_channel_buffer(
|
||||
request: proto::GetChannelBuffer,
|
||||
response: Response<proto::GetChannelBuffer>,
|
||||
async fn open_channel_buffer(
|
||||
request: proto::OpenChannelBuffer,
|
||||
response: Response<proto::OpenChannelBuffer>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
let db = session.db().await;
|
||||
|
@ -2489,9 +2494,12 @@ async fn get_channel_buffer(
|
|||
|
||||
let buffer_id = db.get_or_create_buffer_for_channel(channel_id).await?;
|
||||
|
||||
let buffer = db.get_buffer(buffer_id).await?;
|
||||
// TODO: join channel_buffer
|
||||
|
||||
response.send(GetChannelBufferResponse {
|
||||
let buffer = db.open_buffer(buffer_id).await?;
|
||||
|
||||
response.send(OpenChannelBufferResponse {
|
||||
buffer_id: buffer_id.to_proto(),
|
||||
base_text: buffer.base_text,
|
||||
operations: buffer.operations,
|
||||
})?;
|
||||
|
@ -2499,6 +2507,32 @@ async fn get_channel_buffer(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn close_channel_buffer(
|
||||
request: proto::CloseChannelBuffer,
|
||||
response: Response<proto::CloseChannelBuffer>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
let db = session.db().await;
|
||||
let buffer_id = BufferId::from_proto(request.buffer_id);
|
||||
|
||||
// TODO: close channel buffer here
|
||||
//
|
||||
response.send(Ack {})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_channel_buffer(
|
||||
request: proto::UpdateChannelBuffer,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
let db = session.db().await;
|
||||
|
||||
// TODO: Broadcast to buffer members
|
||||
|
||||
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
|
||||
|
|
|
@ -19,45 +19,39 @@ async fn test_channel_buffers(
|
|||
.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))
|
||||
let channel_buffer_a = cx_a
|
||||
.update(|cx| ChannelBuffer::for_channel(zed_id, client_a.client().to_owned(), 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);
|
||||
let buffer_a = channel_buffer_a.read_with(cx_a, |buffer, _| buffer.buffer());
|
||||
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_a, cx_a),
|
||||
"hello, cruel world"
|
||||
);
|
||||
edit_channel_buffer(&buffer_a, cx_a, [(0..0, "hello world")]);
|
||||
edit_channel_buffer(&buffer_a, cx_a, [(5..5, ", cruel")]);
|
||||
edit_channel_buffer(&buffer_a, cx_a, [(0..5, "goodbye")]);
|
||||
undo_channel_buffer(&buffer_a, cx_a);
|
||||
|
||||
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))
|
||||
assert_eq!(channel_buffer_text(&buffer_a, cx_a), "hello, cruel world");
|
||||
|
||||
let channel_buffer_b = cx_b
|
||||
.update(|cx| ChannelBuffer::for_channel(zed_id, client_b.client().to_owned(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_b, cx_b),
|
||||
"hello, cruel world"
|
||||
);
|
||||
let buffer_b = channel_buffer_b.read_with(cx_b, |buffer, _| buffer.buffer());
|
||||
|
||||
edit_channel_buffer(&channel_buffer_b, cx_b, [(7..12, "beautiful")]);
|
||||
assert_eq!(channel_buffer_text(&buffer_b, cx_b), "hello, cruel world");
|
||||
|
||||
edit_channel_buffer(&buffer_b, cx_b, [(7..12, "beautiful")]);
|
||||
|
||||
deterministic.run_until_parked();
|
||||
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_a, cx_a),
|
||||
channel_buffer_text(&buffer_a, cx_a),
|
||||
"hello, beautiful world"
|
||||
);
|
||||
assert_eq!(
|
||||
channel_buffer_text(&channel_buffer_b, cx_b),
|
||||
channel_buffer_text(&buffer_b, cx_b),
|
||||
"hello, beautiful world"
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue