blatherskite

a toy discord-like chat app backend written for a swe class
Log | Files | Refs | README

commit c78231c5a5ca6f2c22c6cd4ce9ff78eaea2b01db
parent 54e2159763489edb6268bfbb70efe27c2ddb2280
Author: quantumish <freifeld.david@gmail.com>
Date:   Sun, 16 Oct 2022 14:46:39 -0700

[NW] Different (broken) ID generation, simplified tests

Diffstat:
D.pre-commit-config.yaml | 5-----
Mscuttlebutt/src/main.rs | 16++++++++++++++--
Mscuttlebutt/src/tests.rs | 162+++++++++++++++++++++++++++++++------------------------------------------------
3 files changed, 78 insertions(+), 105 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml @@ -1,5 +0,0 @@ -repos: - - repo: https://github.com/doublify/pre-commit-rust - rev: v1.0 - hooks: - - id: cargo-check diff --git a/scuttlebutt/src/main.rs b/scuttlebutt/src/main.rs @@ -40,6 +40,17 @@ struct Claims { )] struct Authorization(Claims); +struct IdGenerator(Snowflake); + +impl Clone for IdGenerator { + fn clone(&self) -> Self { + println!("Cloning from thread {:?}", std::thread::current().id()); + let now = Utc::now().timestamp_nanos(); + // TODO generalize hardcoded numbers + IdGenerator(Snowflake::new(now, 1, 0)) + } +} + async fn api_checker(req: &Request, api_key: ApiKey) -> Option<Claims> { let claims: Claims = serde_json::from_str( &String::from_utf8(base64::decode(api_key.key.split(".").nth(1).unwrap()).unwrap()) @@ -122,12 +133,12 @@ impl Api { #[oai(path = "/user", method = "post")] /// Creates a new user - async fn make_user(&self, name: Query<String>, email: Query<String>, hash: Query<String>) -> CreateUserResponse { + async fn make_user(&self, idgen: Data<&IdGenerator>, name: Query<String>, email: Query<String>, hash: Query<String>) -> CreateUserResponse { use CreateUserResponse::*; if hash.0.len() != 64 { return BadRequest(PlainText("Invalid hash provided.".to_string())); } - let id = gen_id(); + let id = (*idgen.0).0.generate(); self.db.create_user(id, name.0.clone(), email.0.clone(), hash.0).unwrap(); Success(Json(User { id, @@ -433,6 +444,7 @@ async fn main() -> Result<(), std::io::Error> { let app = Route::new() .nest("/api", api_service) .nest("/", ui) + .data(IdGenerator(Snowflake::default())) .data(ServerKey::new_from_slice(&key.as_bytes()).unwrap()); Server::new(TcpListener::bind("127.0.0.1:3000")).run(app).await diff --git a/scuttlebutt/src/tests.rs b/scuttlebutt/src/tests.rs @@ -56,12 +56,38 @@ async fn login(cli: &FakeClient, id: i64, pass: &str) -> String { resp.0.take_body().into_string().await.unwrap() } -async fn setup_user_auth() -> (FakeClient, User, String) { +async fn setup_user_auth() -> (FakeClient, User) { let cli = setup(); let user = make_user(&cli, "test", "test@example.com", "12345").await; let auth = login(&cli, user.id, "12345").await; let cli = cli.default_header("Authorization", &auth); - (cli, user, auth) + let cli = cli.default_content_type("text/plain"); + (cli, user) +} + + +async fn make_group(cli: &FakeClient, name: &str) -> Group { + let resp = cli.post(format!("/api/group?name={}", name)).send().await; + resp.assert_status_is_ok(); + resp.json().await.value().deserialize::<Group>() +} + +async fn make_channel(cli: &FakeClient, gid: i64, name: &str) -> Channel { + let resp = cli.post(format!("/api/group/channels?gid={}&name={}", gid, name)).send().await; + resp.assert_status_is_ok(); + resp.json().await.value().deserialize::<Channel>() +} + +async fn find_channel(cli: &FakeClient, id: i64) -> Channel { + let resp = cli.get(format!("/api/channel?id={}", id)).send().await; + resp.assert_status_is_ok(); + resp.json().await.value().deserialize::<Channel>() +} + +async fn find_group(cli: &FakeClient, id: i64) -> Group { + let resp = cli.get(format!("/api/group?id={}", id)).send().await; + resp.assert_status_is_ok(); + resp.json().await.value().deserialize::<Group>() } #[tokio::test] @@ -128,7 +154,7 @@ async fn get_user() { #[tokio::test] async fn put_user() { - let (cli, user, auth) = setup_user_auth().await; + let (cli, user) = setup_user_auth().await; let resp = cli.put("/api/user?name=fred&email=whoo@whee.com") .header::<&str, &str>("Authorization", "").send().await; @@ -148,7 +174,7 @@ async fn put_user() { #[tokio::test] async fn del_user() { - let (cli, user, auth) = setup_user_auth().await; + let (cli, user) = setup_user_auth().await; let resp = cli.delete(format!("/api/user?id={}", user.id)) .header::<&str, &str>("Authorization", "").send().await; @@ -160,47 +186,9 @@ async fn del_user() { let resp = cli.get(format!("/api/user?id={}", user.id)).send().await; resp.assert_status(StatusCode::NOT_FOUND); } - -async fn make_group(cli: &FakeClient, auth: &str, name: &str) -> Group { - let resp = cli.post(format!("/api/group?name={}", name)) - .send().await; - resp.assert_status_is_ok(); - resp.json().await.value().deserialize::<Group>() -} - -async fn make_channel(cli: &FakeClient, auth: &str, gid: i64, name: &str) -> Channel { - let resp = cli - .post(format!("/api/group/channels?gid={}&name={}", gid, name)) - - .send() - .await; - resp.assert_status_is_ok(); - resp.json().await.value().deserialize::<Channel>() -} - -async fn find_channel(cli: &FakeClient, auth: &str, id: i64) -> Channel { - let resp = cli - .get(format!("/api/channel?id={}", id)) - - .send() - .await; - resp.assert_status_is_ok(); - resp.json().await.value().deserialize::<Channel>() -} - -async fn find_group(cli: &FakeClient, auth: &str, id: i64) -> Group { - let resp = cli - .get(format!("/api/group?id={}", id)) - - .send() - .await; - resp.assert_status_is_ok(); - resp.json().await.value().deserialize::<Group>() -} - #[tokio::test] async fn post_group() { - let (cli, user, auth) = setup_user_auth().await; + let (cli, user) = setup_user_auth().await; let resp = cli.post("/api/group?name=") .send().await; resp.assert_status(StatusCode::BAD_REQUEST); @@ -216,31 +204,24 @@ async fn post_group() { assert_eq!(group.members, vec![user.id]); assert_eq!(group.channels.len(), 1); assert_eq!( - find_channel(&cli, &auth, group.channels[0]).await.name, + find_channel(&cli, group.channels[0]).await.name, String::from("main") ); } #[tokio::test] async fn put_group() { - let (cli, user, auth) = setup_user_auth().await; - let group = make_group(&cli, &auth, "test").await; + let (cli, _user) = setup_user_auth().await; + let group = make_group(&cli, "test").await; let resp = cli.put(format!("/api/group?id={}&name=test2", group.id)) .header::<&str, &str>("Authorization", "").send().await; resp.assert_status(StatusCode::UNAUTHORIZED); - let resp = cli - .put(format!("/api/group?id={}&name=", group.id)) - .send() - .await; + let resp = cli.put(format!("/api/group?id={}&name=", group.id)).send().await; resp.assert_status(StatusCode::BAD_REQUEST); - let resp = cli - .put("/api/group?id=12&name=test2") - - .send() - .await; + let resp = cli.put("/api/group?id=12&name=test2").send().await; resp.assert_status(StatusCode::NOT_FOUND); let resp = cli.put(format!("/api/group?id={}&name=test2", group.id)).send().await; @@ -249,40 +230,34 @@ async fn put_group() { #[tokio::test] async fn del_group() { - let (cli, user, auth) = setup_user_auth().await; - let group = make_group(&cli, &auth, "test").await; + let (cli, _user) = setup_user_auth().await; + let group = make_group(&cli, "test").await; let resp = cli.delete(format!("/api/group?id={}", group.id)) .header::<&str, &str>("Authorization", "").send().await; resp.assert_status(StatusCode::UNAUTHORIZED); - let resp = cli.delete("/api/group?id=12") - .send().await; + let resp = cli.delete("/api/group?id=12").send().await; resp.assert_status(StatusCode::NOT_FOUND); - let resp = cli.delete(format!("/api/group?id={}", group.id)) - .send().await; + let resp = cli.delete(format!("/api/group?id={}", group.id)).send().await; resp.assert_status_is_ok(); - let resp = cli.get(format!("/api/group?id={}", group.id)) - .send().await; - + let resp = cli.get(format!("/api/group?id={}", group.id)).send().await; resp.assert_status(StatusCode::NOT_FOUND); - let resp = cli.get(format!("/api/channel?id={}", group.channels[0])) - .send().await; + let resp = cli.get(format!("/api/channel?id={}", group.channels[0])).send().await; resp.assert_status(StatusCode::NOT_FOUND); - let resp = cli.get("/api/user/groups").send().await; - + let resp = cli.get("/api/user/groups").send().await; resp.assert_status(StatusCode::NOT_FOUND); } #[tokio::test] async fn put_group_members() { - let (cli, user, auth) = setup_user_auth().await; - let group = make_group(&cli, &auth, "test").await; + let (cli, user) = setup_user_auth().await; + let group = make_group(&cli, "test").await; let user2 = make_user(&cli, "testeroo", "test2@example.com", "123456").await; - let user3 = make_user(&cli, "testeroo", "test2@example.com", "123456").await; + let _user3 = make_user(&cli, "testeroo", "test2@example.com", "123456").await; let resp = cli .put(format!("/api/group/members?gid={}&uid={}", group.id, user2.id)) @@ -291,27 +266,18 @@ async fn put_group_members() { .await; resp.assert_status(StatusCode::UNAUTHORIZED); - let resp = cli - .post(format!("/api/group/channels?gid={}&name=", group.id)) - .send() - .await; + let resp = cli.post(format!("/api/group/channels?gid={}&name=", group.id)).send().await; resp.assert_status(StatusCode::BAD_REQUEST); - let resp = cli - .post("/api/group/channels?gid=12&name=test") - .send() - .await; + let resp = cli.post("/api/group/channels?gid=12&name=test").send().await; resp.assert_status(StatusCode::NOT_FOUND); - let resp = cli - .post(format!("/api/group/channels?gid={}&name=test", group.id)) - .send() - .await; + let resp = cli.post(format!("/api/group/channels?gid={}&name=test", group.id)).send().await; resp.assert_status_is_ok(); let channel = resp.json().await.value().deserialize::<Channel>(); assert_eq!(channel.name, "test"); assert_eq!(channel.members, vec![user.id]); - assert!(find_group(&cli, &auth, group.id).await.channels.contains(&channel.id)); + assert!(find_group(&cli, group.id).await.channels.contains(&channel.id)); } #[test] /// Test if gen_id() gives unique IDs on successive calls @@ -329,9 +295,9 @@ fn test_id_gen() { #[tokio::test] async fn get_channel() { - let (cli, _user, auth) = setup_user_auth().await; - let group = make_group(&cli, &auth, "test").await; - let chan = make_channel(&cli, &auth, group.id, "random").await; + let (cli, _user) = setup_user_auth().await; + let group = make_group(&cli, "test").await; + let chan = make_channel(&cli, group.id, "random").await; let resp = cli.get(format!("/api/channel?id={}", chan.id)).send().await; resp.assert_status_is_ok(); let recv_chan = resp.json().await.value().deserialize::<Channel>(); @@ -341,26 +307,26 @@ async fn get_channel() { // FIXME non exhaustive #[tokio::test] async fn get_channels() { - let (cli, _user, auth) = setup_user_auth().await; - let group = make_group(&cli, &auth, "test").await; - let chan1 = make_channel(&cli, &auth, group.id, "random").await; - let chan2 = make_channel(&cli, &auth, group.id, "random").await; - let chan3 = make_channel(&cli, &auth, group.id, "random").await; + let (cli, _user) = setup_user_auth().await; + let group = make_group(&cli, "test").await; + let chan1 = make_channel(&cli, group.id, "random").await; + let chan2 = make_channel(&cli, group.id, "random").await; + let chan3 = make_channel(&cli, group.id, "random").await; let resp = cli.get(format!("/api/group/channels?gid={}", group.id)).send().await; resp.assert_status_is_ok(); let channels = resp.json().await.value().deserialize::<Vec<Channel>>(); assert!(contents_eq( channels, - vec![find_channel(&cli, &auth, group.channels[0]).await, chan1, chan2, chan3] + vec![find_channel(&cli, group.channels[0]).await, chan1, chan2, chan3] )); } #[tokio::test] async fn get_groups() { - let (cli, _user, auth) = setup_user_auth().await; - let group = make_group(&cli, &auth, "test1").await; - let group2 = make_group(&cli, &auth, "test2").await; - let group3 = make_group(&cli, &auth, "test3").await; + let (cli, _user) = setup_user_auth().await; + let group = make_group(&cli, "test1").await; + let group2 = make_group(&cli, "test2").await; + let group3 = make_group(&cli, "test3").await; let resp = cli.get("/api/user/groups").send().await; resp.assert_status_is_ok(); let groups = resp.json().await.value().deserialize::<Vec<Group>>(); @@ -369,6 +335,6 @@ async fn get_groups() { // #[tokio::test] // async fn get_group_members() { -// let (cli, user, auth) = setup_user_auth().await; +// let (cli, user) = setup_user_auth().await; // let group = make_group(&cli, auth.clone(), "test").await; // }