This commit is contained in:
Antonio Scandurra 2023-10-22 12:21:28 +02:00
parent 909fbb9538
commit f4135e6bcf
12 changed files with 860 additions and 637 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL};
use gpui::{executor::Background, serde_json, AppContext, Task};
use gpui2::{serde_json, AppContext, Executor, Task};
use lazy_static::lazy_static;
use parking_lot::Mutex;
use serde::Serialize;
@ -11,7 +11,7 @@ use util::{channel::ReleaseChannel, TryFutureExt};
pub struct Telemetry {
http_client: Arc<dyn HttpClient>,
executor: Arc<Background>,
executor: Executor,
state: Mutex<TelemetryState>,
}

View file

@ -1,215 +1,215 @@
use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore};
use anyhow::{anyhow, Result};
use futures::{stream::BoxStream, StreamExt};
use gpui::{executor, ModelHandle, TestAppContext};
use parking_lot::Mutex;
use rpc::{
proto::{self, GetPrivateUserInfo, GetPrivateUserInfoResponse},
ConnectionId, Peer, Receipt, TypedEnvelope,
};
use std::{rc::Rc, sync::Arc};
use util::http::FakeHttpClient;
// use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore};
// use anyhow::{anyhow, Result};
// use futures::{stream::BoxStream, StreamExt};
// use gpui2::{Executor, Handle, TestAppContext};
// use parking_lot::Mutex;
// use rpc::{
// proto::{self, GetPrivateUserInfo, GetPrivateUserInfoResponse},
// ConnectionId, Peer, Receipt, TypedEnvelope,
// };
// use std::{rc::Rc, sync::Arc};
// use util::http::FakeHttpClient;
pub struct FakeServer {
peer: Arc<Peer>,
state: Arc<Mutex<FakeServerState>>,
user_id: u64,
executor: Rc<executor::Foreground>,
}
// pub struct FakeServer {
// peer: Arc<Peer>,
// state: Arc<Mutex<FakeServerState>>,
// user_id: u64,
// executor: Executor,
// }
#[derive(Default)]
struct FakeServerState {
incoming: Option<BoxStream<'static, Box<dyn proto::AnyTypedEnvelope>>>,
connection_id: Option<ConnectionId>,
forbid_connections: bool,
auth_count: usize,
access_token: usize,
}
// #[derive(Default)]
// struct FakeServerState {
// incoming: Option<BoxStream<'static, Box<dyn proto::AnyTypedEnvelope>>>,
// connection_id: Option<ConnectionId>,
// forbid_connections: bool,
// auth_count: usize,
// access_token: usize,
// }
impl FakeServer {
pub async fn for_client(
client_user_id: u64,
client: &Arc<Client>,
cx: &TestAppContext,
) -> Self {
let server = Self {
peer: Peer::new(0),
state: Default::default(),
user_id: client_user_id,
executor: cx.foreground(),
};
// impl FakeServer {
// pub async fn for_client(
// client_user_id: u64,
// client: &Arc<Client>,
// cx: &TestAppContext,
// ) -> Self {
// let server = Self {
// peer: Peer::new(0),
// state: Default::default(),
// user_id: client_user_id,
// executor: cx.foreground(),
// };
client
.override_authenticate({
let state = Arc::downgrade(&server.state);
move |cx| {
let state = state.clone();
cx.spawn(move |_| async move {
let state = state.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
let mut state = state.lock();
state.auth_count += 1;
let access_token = state.access_token.to_string();
Ok(Credentials {
user_id: client_user_id,
access_token,
})
})
}
})
.override_establish_connection({
let peer = Arc::downgrade(&server.peer);
let state = Arc::downgrade(&server.state);
move |credentials, cx| {
let peer = peer.clone();
let state = state.clone();
let credentials = credentials.clone();
cx.spawn(move |cx| async move {
let state = state.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
let peer = peer.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
if state.lock().forbid_connections {
Err(EstablishConnectionError::Other(anyhow!(
"server is forbidding connections"
)))?
}
// client
// .override_authenticate({
// let state = Arc::downgrade(&server.state);
// move |cx| {
// let state = state.clone();
// cx.spawn(move |_| async move {
// let state = state.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
// let mut state = state.lock();
// state.auth_count += 1;
// let access_token = state.access_token.to_string();
// Ok(Credentials {
// user_id: client_user_id,
// access_token,
// })
// })
// }
// })
// .override_establish_connection({
// let peer = Arc::downgrade(&server.peer);
// let state = Arc::downgrade(&server.state);
// move |credentials, cx| {
// let peer = peer.clone();
// let state = state.clone();
// let credentials = credentials.clone();
// cx.spawn(move |cx| async move {
// let state = state.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
// let peer = peer.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
// if state.lock().forbid_connections {
// Err(EstablishConnectionError::Other(anyhow!(
// "server is forbidding connections"
// )))?
// }
assert_eq!(credentials.user_id, client_user_id);
// assert_eq!(credentials.user_id, client_user_id);
if credentials.access_token != state.lock().access_token.to_string() {
Err(EstablishConnectionError::Unauthorized)?
}
// if credentials.access_token != state.lock().access_token.to_string() {
// Err(EstablishConnectionError::Unauthorized)?
// }
let (client_conn, server_conn, _) = Connection::in_memory(cx.background());
let (connection_id, io, incoming) =
peer.add_test_connection(server_conn, cx.background());
cx.background().spawn(io).detach();
{
let mut state = state.lock();
state.connection_id = Some(connection_id);
state.incoming = Some(incoming);
}
peer.send(
connection_id,
proto::Hello {
peer_id: Some(connection_id.into()),
},
)
.unwrap();
// let (client_conn, server_conn, _) = Connection::in_memory(cx.background());
// let (connection_id, io, incoming) =
// peer.add_test_connection(server_conn, cx.background());
// cx.background().spawn(io).detach();
// {
// let mut state = state.lock();
// state.connection_id = Some(connection_id);
// state.incoming = Some(incoming);
// }
// peer.send(
// connection_id,
// proto::Hello {
// peer_id: Some(connection_id.into()),
// },
// )
// .unwrap();
Ok(client_conn)
})
}
});
// Ok(client_conn)
// })
// }
// });
client
.authenticate_and_connect(false, &cx.to_async())
.await
.unwrap();
// client
// .authenticate_and_connect(false, &cx.to_async())
// .await
// .unwrap();
server
}
// server
// }
pub fn disconnect(&self) {
if self.state.lock().connection_id.is_some() {
self.peer.disconnect(self.connection_id());
let mut state = self.state.lock();
state.connection_id.take();
state.incoming.take();
}
}
// pub fn disconnect(&self) {
// if self.state.lock().connection_id.is_some() {
// self.peer.disconnect(self.connection_id());
// let mut state = self.state.lock();
// state.connection_id.take();
// state.incoming.take();
// }
// }
pub fn auth_count(&self) -> usize {
self.state.lock().auth_count
}
// pub fn auth_count(&self) -> usize {
// self.state.lock().auth_count
// }
pub fn roll_access_token(&self) {
self.state.lock().access_token += 1;
}
// pub fn roll_access_token(&self) {
// self.state.lock().access_token += 1;
// }
pub fn forbid_connections(&self) {
self.state.lock().forbid_connections = true;
}
// pub fn forbid_connections(&self) {
// self.state.lock().forbid_connections = true;
// }
pub fn allow_connections(&self) {
self.state.lock().forbid_connections = false;
}
// pub fn allow_connections(&self) {
// self.state.lock().forbid_connections = false;
// }
pub fn send<T: proto::EnvelopedMessage>(&self, message: T) {
self.peer.send(self.connection_id(), message).unwrap();
}
// pub fn send<T: proto::EnvelopedMessage>(&self, message: T) {
// self.peer.send(self.connection_id(), message).unwrap();
// }
#[allow(clippy::await_holding_lock)]
pub async fn receive<M: proto::EnvelopedMessage>(&self) -> Result<TypedEnvelope<M>> {
self.executor.start_waiting();
// #[allow(clippy::await_holding_lock)]
// pub async fn receive<M: proto::EnvelopedMessage>(&self) -> Result<TypedEnvelope<M>> {
// self.executor.start_waiting();
loop {
let message = self
.state
.lock()
.incoming
.as_mut()
.expect("not connected")
.next()
.await
.ok_or_else(|| anyhow!("other half hung up"))?;
self.executor.finish_waiting();
let type_name = message.payload_type_name();
let message = message.into_any();
// loop {
// let message = self
// .state
// .lock()
// .incoming
// .as_mut()
// .expect("not connected")
// .next()
// .await
// .ok_or_else(|| anyhow!("other half hung up"))?;
// self.executor.finish_waiting();
// let type_name = message.payload_type_name();
// let message = message.into_any();
if message.is::<TypedEnvelope<M>>() {
return Ok(*message.downcast().unwrap());
}
// if message.is::<TypedEnvelope<M>>() {
// return Ok(*message.downcast().unwrap());
// }
if message.is::<TypedEnvelope<GetPrivateUserInfo>>() {
self.respond(
message
.downcast::<TypedEnvelope<GetPrivateUserInfo>>()
.unwrap()
.receipt(),
GetPrivateUserInfoResponse {
metrics_id: "the-metrics-id".into(),
staff: false,
flags: Default::default(),
},
);
continue;
}
// if message.is::<TypedEnvelope<GetPrivateUserInfo>>() {
// self.respond(
// message
// .downcast::<TypedEnvelope<GetPrivateUserInfo>>()
// .unwrap()
// .receipt(),
// GetPrivateUserInfoResponse {
// metrics_id: "the-metrics-id".into(),
// staff: false,
// flags: Default::default(),
// },
// );
// continue;
// }
panic!(
"fake server received unexpected message type: {:?}",
type_name
);
}
}
// panic!(
// "fake server received unexpected message type: {:?}",
// type_name
// );
// }
// }
pub fn respond<T: proto::RequestMessage>(&self, receipt: Receipt<T>, response: T::Response) {
self.peer.respond(receipt, response).unwrap()
}
// pub fn respond<T: proto::RequestMessage>(&self, receipt: Receipt<T>, response: T::Response) {
// self.peer.respond(receipt, response).unwrap()
// }
fn connection_id(&self) -> ConnectionId {
self.state.lock().connection_id.expect("not connected")
}
// fn connection_id(&self) -> ConnectionId {
// self.state.lock().connection_id.expect("not connected")
// }
pub async fn build_user_store(
&self,
client: Arc<Client>,
cx: &mut TestAppContext,
) -> ModelHandle<UserStore> {
let http_client = FakeHttpClient::with_404_response();
let user_store = cx.add_model(|cx| UserStore::new(client, http_client, cx));
assert_eq!(
self.receive::<proto::GetUsers>()
.await
.unwrap()
.payload
.user_ids,
&[self.user_id]
);
user_store
}
}
// pub async fn build_user_store(
// &self,
// client: Arc<Client>,
// cx: &mut TestAppContext,
// ) -> ModelHandle<UserStore> {
// let http_client = FakeHttpClient::with_404_response();
// let user_store = cx.add_model(|cx| UserStore::new(client, http_client, cx));
// assert_eq!(
// self.receive::<proto::GetUsers>()
// .await
// .unwrap()
// .payload
// .user_ids,
// &[self.user_id]
// );
// user_store
// }
// }
impl Drop for FakeServer {
fn drop(&mut self) {
self.disconnect();
}
}
// impl Drop for FakeServer {
// fn drop(&mut self) {
// self.disconnect();
// }
// }

View file

@ -3,7 +3,7 @@ use anyhow::{anyhow, Context, Result};
use collections::{hash_map::Entry, HashMap, HashSet};
use feature_flags::FeatureFlagAppExt;
use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt};
use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task};
use gpui2::{AsyncAppContext, EventEmitter, Handle, ImageData, ModelContext, Task};
use postage::{sink::Sink, watch};
use rpc::proto::{RequestMessage, UsersResponse};
use std::sync::{Arc, Weak};
@ -103,7 +103,7 @@ pub enum ContactEventKind {
Cancelled,
}
impl Entity for UserStore {
impl EventEmitter for UserStore {
type Event = Event;
}
@ -217,7 +217,7 @@ impl UserStore {
}
async fn handle_update_invite_info(
this: ModelHandle<Self>,
this: Handle<Self>,
message: TypedEnvelope<proto::UpdateInviteInfo>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@ -233,7 +233,7 @@ impl UserStore {
}
async fn handle_show_contacts(
this: ModelHandle<Self>,
this: Handle<Self>,
_: TypedEnvelope<proto::ShowContacts>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@ -247,7 +247,7 @@ impl UserStore {
}
async fn handle_update_contacts(
this: ModelHandle<Self>,
this: Handle<Self>,
message: TypedEnvelope<proto::UpdateContacts>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@ -689,7 +689,7 @@ impl User {
impl Contact {
async fn from_proto(
contact: proto::Contact,
user_store: &ModelHandle<UserStore>,
user_store: &Handle<UserStore>,
cx: &mut AsyncAppContext,
) -> Result<Self> {
let user = user_store