tests.rs (18324B)
1 use super::*; 2 3 use hmac::Mac; 4 use more_asserts::*; 5 use poem::{ 6 http::StatusCode, 7 middleware::AddDataEndpoint, 8 test::TestClient, 9 Route, 10 }; 11 use pretty_assertions::assert_eq; 12 use sha2::Digest; 13 14 type FakeClient = TestClient<AddDataEndpoint<Route, ServerKey>>; 15 16 fn contents_eq<T: PartialEq>(a: Vec<T>, b: Vec<T>) -> bool { 17 b.iter().all(|item| a.contains(item)) 18 } 19 20 fn setup() -> FakeClient { 21 let key: String = rand::thread_rng() 22 .sample_iter(&Alphanumeric) 23 .take(7) 24 .map(char::from) 25 .collect(); 26 let db = Box::new(Cassandra::new("test")); 27 let api_service = OpenApiService::new(Api::new(db), "Scuttlebutt", "1.0").server("http://localhost:3000/api"); 28 let app = Route::new() 29 .nest("/api", api_service) 30 .data(ServerKey::new_from_slice(&key.as_bytes()).unwrap()); 31 TestClient::new(app) 32 } 33 34 fn hash_pass(pass: &str) -> String { 35 let mut hasher = Sha256::new(); 36 hasher.update(pass); 37 hex::encode(hasher.finalize()) 38 } 39 40 async fn make_user(cli: &FakeClient, name: &str, email: &str, pass: &str) -> User { 41 let hash = hash_pass(pass); 42 let resp = cli.post(format!("/api/user?name={}&email={}", name, email)) 43 .content_type("text/plain").body(hash).send().await; 44 resp.assert_status_is_ok(); 45 resp.json().await.value().deserialize::<User>() 46 } 47 48 async fn login(cli: &FakeClient, id: i64, pass: &str) -> String { 49 let hash = hash_pass(pass); 50 let mut resp = cli.post(format!("/api/login?id={}", id)).content_type("text/plain").body(hash).send().await; 51 resp.assert_status_is_ok(); 52 resp.0.take_body().into_string().await.unwrap() 53 } 54 55 async fn user_auth(cli: &FakeClient, name: &str, email: &str, pass: &str) -> (User, String) { 56 let user = make_user(&cli, name, email, pass).await; 57 let auth = login(&cli, user.id, pass).await; 58 (user, auth) 59 } 60 61 async fn setup_user_auth() -> (FakeClient, User) { 62 let cli = setup(); 63 let (user, auth) = user_auth(&cli, "test", "test@example.com", "12345").await; 64 let cli = cli.default_header("Authorization", &auth); 65 (cli, user) 66 } 67 68 async fn make_group(cli: &FakeClient, name: &str) -> Group { 69 let resp = cli.post(format!("/api/group?name={}", name)).send().await; 70 resp.assert_status_is_ok(); 71 resp.json().await.value().deserialize::<Group>() 72 } 73 74 async fn add_group_member(cli: &FakeClient, gid: i64, uid: i64) { 75 let resp = cli.put(format!("/api/group/members?gid={}&uid={}", gid, uid)).send().await; 76 resp.assert_status_is_ok(); 77 } 78 79 async fn make_dm(cli: &FakeClient, uid: i64) -> Group { 80 let resp = cli.post(format!("/api/dm?uid={}", uid)).send().await; 81 resp.assert_status_is_ok(); 82 resp.json().await.value().deserialize::<Group>() 83 } 84 85 async fn find_groups(cli: &FakeClient) -> Vec<Group> { 86 let resp = cli.post("/api/user/groups").send().await; 87 resp.assert_status_is_ok(); 88 resp.json().await.value().deserialize::<Vec<Group>>() 89 } 90 91 async fn make_channel(cli: &FakeClient, gid: i64, name: &str) -> Channel { 92 let resp = cli.post(format!("/api/group/channels?gid={}&name={}", gid, name)).send().await; 93 resp.assert_status_is_ok(); 94 resp.json().await.value().deserialize::<Channel>() 95 } 96 97 async fn find_channel(cli: &FakeClient, id: i64) -> Channel { 98 let resp = cli.get(format!("/api/channel?id={}", id)).send().await; 99 resp.assert_status_is_ok(); 100 resp.json().await.value().deserialize::<Channel>() 101 } 102 103 async fn find_group(cli: &FakeClient, id: i64) -> Group { 104 let resp = cli.get(format!("/api/group?id={}", id)).send().await; 105 resp.assert_status_is_ok(); 106 resp.json().await.value().deserialize::<Group>() 107 } 108 109 #[tokio::test] 110 async fn post_login() { 111 let cli = setup(); 112 let user = make_user(&cli, "test", "test@example.com", "12345").await; 113 let hash = hash_pass("12345"); 114 115 let resp = cli.post(format!("/api/login?id={}", user.id)) 116 .content_type("text/plain").body("abc").send().await; 117 resp.assert_status(StatusCode::BAD_REQUEST); 118 let resp = cli.post(format!("/api/login?id={}", user.id)) 119 .content_type("text/plain").send().await; 120 resp.assert_status(StatusCode::BAD_REQUEST); 121 122 let resp = cli.post("/api/login?id=12") 123 .content_type("text/plain").body(hash.clone()).send().await; 124 resp.assert_status(StatusCode::NOT_FOUND); 125 126 let resp = cli.post(format!("/api/login?id={}", user.id)) 127 .header::<&str, &str>("Authorization", "") 128 .content_type("text/plain").body(hash_pass("123")).send().await; 129 resp.assert_status(StatusCode::UNAUTHORIZED); 130 131 let mut resp = cli.post(format!("/api/login?id={}", user.id)) 132 .content_type("text/plain").body(hash.clone()).send().await; 133 resp.assert_status_is_ok(); 134 let raw_str = resp.0.take_body().into_string().await.unwrap(); 135 let claims: Claims = serde_json::from_str(&String::from_utf8(base64::decode( 136 raw_str.split(".").nth(1).unwrap() 137 ).unwrap()).unwrap()).unwrap(); 138 assert_eq!(claims.id, user.id); 139 assert_ge!(claims.exp, Local::now()) 140 } 141 142 #[tokio::test] 143 async fn get_user() { 144 let cli = setup(); 145 let user = make_user(&cli, "test", "test@example.com", "12345").await; 146 let resp = cli.get("/api/user?id=12").send().await; 147 resp.assert_status(StatusCode::NOT_FOUND); 148 let resp = cli.get(format!("/api/user?id={}", user.id)).send().await; 149 resp.assert_status_is_ok(); 150 let ret_user = resp.json().await.value().deserialize::<User>(); 151 assert_eq!(user, ret_user); 152 } 153 154 #[tokio::test] 155 async fn post_user() { 156 let cli = setup(); 157 let user = make_user(&cli, "test", "test@example.com", "12345").await; 158 159 assert_eq!(user.email, "test@example.com"); 160 assert_eq!(user.username, "test"); 161 162 let resp = cli.get(format!("/api/user?id={}", user.id)).send().await; 163 resp.assert_status_is_ok(); 164 165 let same_user = resp.json().await.value().deserialize::<User>(); 166 assert_eq!(user, same_user); 167 } 168 169 #[tokio::test] 170 async fn post_user_whitebox() { 171 let cli = setup(); 172 let user = make_user(&cli, "test", "test@example.com", "12345").await; 173 let db = Cassandra::new("test"); 174 assert_eq!(db.get_user(user.id).unwrap(), user); 175 assert_eq!(db.get_user_groups(user.id).unwrap(), Vec::<i64>::new()); 176 } 177 178 #[tokio::test] 179 async fn put_user() { 180 let (cli, user) = setup_user_auth().await; 181 182 let resp = cli.put("/api/user?name=fred&email=whoo@whee.com") 183 .header::<&str, &str>("Authorization", "").send().await; 184 resp.assert_status(StatusCode::UNAUTHORIZED); 185 186 let resp = cli.put("/api/user?name=fred&email=whoo@whee.com").send().await; 187 resp.assert_status_is_ok(); 188 189 let resp = cli.get(format!("/api/user?id={}", user.id)).send().await; 190 resp.assert_status_is_ok(); 191 let ret_user = resp.json().await.value().deserialize::<User>(); 192 assert_eq!(ret_user.email, "whoo@whee.com"); 193 assert_eq!(ret_user.username, "fred"); 194 // User should retain their underlying ID 195 assert_eq!(user.id, ret_user.id); 196 } 197 198 #[tokio::test] 199 /// FIXME non exhaustive 200 async fn del_user() { 201 let (cli, user) = setup_user_auth().await; 202 203 let resp = cli.delete(format!("/api/user?id={}", user.id)) 204 .header::<&str, &str>("Authorization", "").send().await; 205 resp.assert_status(StatusCode::UNAUTHORIZED); 206 207 let resp = cli.delete(format!("/api/user?id={}", user.id)).send().await; 208 209 resp.assert_status_is_ok(); 210 let resp = cli.get(format!("/api/user?id={}", user.id)).send().await; 211 resp.assert_status(StatusCode::NOT_FOUND); 212 } 213 214 #[tokio::test] 215 async fn post_group() { 216 let (cli, user) = setup_user_auth().await; 217 let resp = cli.post("/api/group?name=test") 218 .header::<&str, &str>("Authorization", "").send().await; 219 resp.assert_status(StatusCode::UNAUTHORIZED); 220 221 let resp = cli.post("/api/group?name=").send().await; 222 resp.assert_status(StatusCode::BAD_REQUEST); 223 let resp = cli.post("/api/group?name=test").send().await; 224 resp.assert_status_is_ok(); 225 226 let group = resp.json().await.value().deserialize::<Group>(); 227 assert_eq!(group.name, "test"); 228 assert_eq!(group.members, vec![user.id]); 229 assert_eq!(group.admin, vec![user.id]); 230 assert_eq!(group.owner, user.id); 231 assert_eq!(group.channels.len(), 1); 232 233 let channel = find_channel(&cli, group.channels[0]).await; 234 assert_eq!(channel.members, vec![user.id]); 235 assert_eq!(channel.private, false); 236 assert_eq!( 237 find_channel(&cli, group.channels[0]).await.name, 238 String::from("main") 239 ); 240 } 241 242 #[tokio::test] 243 async fn post_dm() { 244 let (cli, user) = setup_user_auth().await; 245 let (user2, auth2) = user_auth(&cli, "user2", "who@cares.com", "12").await; 246 let resp = cli.post("/api/dm?uid=12") 247 .header::<&str, &str>("Authorization", "").send().await; 248 resp.assert_status(StatusCode::UNAUTHORIZED); 249 250 let resp = cli.post(format!("/api/dm?uid={}", user2.id)).send().await; 251 resp.assert_status_is_ok(); 252 253 let group = resp.json().await.value().deserialize::<Group>(); 254 assert_eq!(group.name, ""); 255 assert_eq!(group.members, vec![user.id, user2.id]); 256 assert_eq!(group.admin, Vec::<i64>::new()); 257 assert_eq!(group.owner, user.id); 258 assert_eq!(group.channels.len(), 1); 259 } 260 261 #[tokio::test] 262 async fn post_dm_whitebox() { 263 let (cli, user) = setup_user_auth().await; 264 let (user2, auth2) = user_auth(&cli, "user2", "who@cares.com", "12").await; 265 let resp = cli.post(format!("/api/dm?uid={}", user2.id)).send().await; 266 resp.assert_status_is_ok(); 267 let dm = resp.json().await.value().deserialize::<Group>(); 268 269 let db = Cassandra::new("test"); 270 assert_eq!(db.get_group(dm.id).unwrap(), dm); 271 assert_eq!(db.get_user_dms(user.id).unwrap(), vec![dm.id]); 272 } 273 274 #[tokio::test] 275 async fn put_group() { 276 let (cli, _user) = setup_user_auth().await; 277 let (user2, auth2) = user_auth(&cli, "user2", "who@cares.com", "12").await; 278 let group = make_group(&cli, "test").await; 279 add_group_member(&cli, group.id, user2.id).await; 280 281 let resp = cli.put(format!("/api/group?id={}&name=test2", group.id)) 282 .header::<&str, &str>("Authorization", "").send().await; 283 resp.assert_status(StatusCode::UNAUTHORIZED); 284 let resp = cli.put(format!("/api/group?id={}&name=test2", group.id)) 285 .header::<&str, &str>("Authorization", &auth2).send().await; 286 resp.assert_status(StatusCode::UNAUTHORIZED); 287 288 let resp = cli.put(format!("/api/group?id={}&name=", group.id)).send().await; 289 resp.assert_status(StatusCode::BAD_REQUEST); 290 291 let resp = cli.put("/api/group?id=12&name=test2").send().await; 292 resp.assert_status(StatusCode::NOT_FOUND); 293 294 let resp = cli.put(format!("/api/group?id={}&name=test2", group.id)).send().await; 295 resp.assert_status_is_ok(); 296 297 let group = find_group(&cli, group.id).await; 298 assert_eq!(group.name, String::from("test2")); 299 } 300 301 #[tokio::test] 302 /// TODO non exhaustive 303 async fn del_group() { 304 let (cli, _user) = setup_user_auth().await; 305 let group = make_group(&cli, "test").await; 306 307 let resp = cli.delete(format!("/api/group?id={}", group.id)) 308 .header::<&str, &str>("Authorization", "").send().await; 309 resp.assert_status(StatusCode::UNAUTHORIZED); 310 311 let resp = cli.delete("/api/group?id=12").send().await; 312 resp.assert_status(StatusCode::NOT_FOUND); 313 314 let resp = cli.delete(format!("/api/group?id={}", group.id)).send().await; 315 resp.assert_status_is_ok(); 316 317 let resp = cli.get(format!("/api/group?id={}", group.id)).send().await; 318 resp.assert_status(StatusCode::NOT_FOUND); 319 let resp = cli.get(format!("/api/channel?id={}", group.channels[0])).send().await; 320 resp.assert_status(StatusCode::NOT_FOUND); 321 322 let resp = cli.get("/api/user/groups").send().await; 323 resp.assert_status_is_ok(); 324 let groups = resp.json().await.value().deserialize::<Vec<Group>>(); 325 assert!(!groups.contains(&group)); 326 } 327 328 // #[tokio::test] 329 // async fn get_group_members() { 330 // let (cli, user) = setup_user_auth().await; 331 // let group = make_group(&cli, auth.clone(), "test").await; 332 // add_group_member 333 // } 334 335 #[tokio::test] 336 /// TODO non exhaustive 337 async fn put_group_members() { 338 let (cli, user) = setup_user_auth().await; 339 let group = make_group(&cli, "test").await; 340 let user2 = make_user(&cli, "testeroo", "test2@example.com", "123456").await; 341 342 let resp = cli.put(format!("/api/group/members?gid={}&uid={}", group.id, user2.id)) 343 .header::<&str, &str>("Authorization", "").send().await; 344 resp.assert_status(StatusCode::UNAUTHORIZED); 345 346 let resp = cli.put(format!("/api/group/members?gid={}&uid=", group.id)).send().await; 347 resp.assert_status(StatusCode::BAD_REQUEST); 348 349 let resp = cli.put(format!("/api/group/members?gid=12&uid={}", user.id)).send().await; 350 resp.assert_status(StatusCode::NOT_FOUND); 351 352 let resp = cli.put(format!("/api/group/members?gid={}&uid={}", group.id, user2.id)).send().await; 353 resp.assert_status_is_ok(); 354 355 assert!(find_group(&cli, group.id).await.members.contains(&user2.id)); 356 } 357 #[test] 358 /// Test if gen_id() gives unique IDs on successive calls 359 /// and if it can be called from multiple threads without error 360 fn test_id_gen() { 361 let a = gen_id(); 362 std::thread::sleep(std::time::Duration::from_secs(1)); 363 let b = gen_id(); 364 assert_ge!(b, a); 365 let threads: Vec<_> = (0..100).map(|i| std::thread::spawn(move || gen_id())).collect(); 366 for handle in threads { 367 handle.join().unwrap(); 368 } 369 } 370 371 #[tokio::test] 372 async fn get_channel() { 373 let (cli, _user) = setup_user_auth().await; 374 let group = make_group(&cli, "test").await; 375 let chan = make_channel(&cli, group.id, "random").await; 376 let resp = cli.get(format!("/api/channel?id={}", chan.id)).send().await; 377 resp.assert_status_is_ok(); 378 let recv_chan = resp.json().await.value().deserialize::<Channel>(); 379 assert_eq!(chan, recv_chan); 380 } 381 382 383 #[tokio::test] 384 async fn post_channel_whitebox() { 385 let (cli, _user) = setup_user_auth().await; 386 let group = make_group(&cli, "test").await; 387 let chan = make_channel(&cli, group.id, "random").await; 388 389 let db = Cassandra::new("test"); 390 assert_eq!(db.get_channel(chan.id).unwrap(), chan); 391 assert!(db.get_group_channels(group.id).unwrap().contains(&chan.id)); 392 } 393 394 395 // FIXME non exhaustive 396 #[tokio::test] 397 async fn get_channels() { 398 let (cli, _user) = setup_user_auth().await; 399 let group = make_group(&cli, "test").await; 400 let chan1 = make_channel(&cli, group.id, "random").await; 401 let chan2 = make_channel(&cli, group.id, "random").await; 402 let chan3 = make_channel(&cli, group.id, "random").await; 403 let resp = cli.get(format!("/api/group/channels?gid={}", group.id)).send().await; 404 resp.assert_status_is_ok(); 405 let channels = resp.json().await.value().deserialize::<Vec<Channel>>(); 406 407 assert!(contents_eq( 408 channels, 409 vec![find_channel(&cli, group.channels[0]).await, chan1, chan2, chan3] 410 )); 411 } 412 413 #[tokio::test] 414 async fn get_group() { 415 let (cli, _user) = setup_user_auth().await; 416 let (user2, auth2) = user_auth(&cli, "wehee", "who@cares.com", "12").await; 417 let group = make_group(&cli, "test1").await; 418 let group2 = make_group(&cli, "test2").await; 419 add_group_member(&cli, group2.id, user2.id).await; 420 421 let resp = cli.get(format!("/api/group?id={}", group.id)).send().await; 422 resp.assert_status_is_ok(); 423 let recv_group = resp.json().await.value().deserialize::<Group>(); 424 assert_eq!(group, recv_group); 425 426 let resp = cli.get(format!("/api/group?id={}", group.id)) 427 .header::<&str, &str>("Authorization", &auth2).send().await; 428 resp.assert_status(StatusCode::NOT_FOUND); 429 } 430 431 #[tokio::test] 432 async fn get_groups() { 433 let (cli, _user) = setup_user_auth().await; 434 let (user2, auth2) = user_auth(&cli, "wehee", "who@cares.com", "12").await; 435 let group = make_group(&cli, "test1").await; 436 add_group_member(&cli, group.id, user2.id).await; 437 let group = find_group(&cli, group.id).await; 438 let group2 = make_group(&cli, "test2").await; 439 let group3 = make_group(&cli, "test3").await; 440 441 let resp = cli.get("/api/user/groups").send().await; 442 resp.assert_status_is_ok(); 443 let groups = resp.json().await.value().deserialize::<Vec<Group>>(); 444 assert!(contents_eq(groups, vec![group.clone(), group2, group3])); 445 446 let resp = cli.get("/api/user/groups") 447 .header::<&str, &str>("Authorization", &auth2).send().await; 448 resp.assert_status_is_ok(); 449 let groups = resp.json().await.value().deserialize::<Vec<Group>>(); 450 assert!(contents_eq(groups, vec![group])); 451 } 452 453 #[tokio::test] 454 async fn get_dms() { 455 let (cli, _user) = setup_user_auth().await; 456 let (user2, auth2) = user_auth(&cli, "wehee", "who@cares.com", "12").await; 457 let (user3, auth3) = user_auth(&cli, "whoo", "why@ask.com", "11").await; 458 let dm1 = make_dm(&cli, user2.id).await; 459 add_group_member(&cli, dm1.id, user3.id).await; 460 let dm2 = make_dm(&cli, user3.id).await; 461 let dm1 = find_group(&cli, dm1.id).await; 462 let dm2 = find_group(&cli, dm2.id).await; 463 464 let resp = cli.get("/api/user/dms").send().await; 465 resp.assert_status_is_ok(); 466 let dms = resp.json().await.value().deserialize::<Vec<Group>>(); 467 assert!(contents_eq(dms, vec![dm1.clone(), dm2.clone()])); 468 469 let resp = cli.get("/api/user/dms") 470 .header::<&str, &str>("Authorization", &auth2).send().await; 471 resp.assert_status_is_ok(); 472 let dms = resp.json().await.value().deserialize::<Vec<Group>>(); 473 assert!(contents_eq(dms, vec![dm1.clone()])); 474 475 let resp = cli.get("/api/user/dms") 476 .header::<&str, &str>("Authorization", &auth3).send().await; 477 resp.assert_status_is_ok(); 478 let dms = resp.json().await.value().deserialize::<Vec<Group>>(); 479 assert!(contents_eq(dms, vec![dm1.clone(), dm2.clone()])); 480 } 481 482 #[tokio::test] 483 async fn leave_group() { 484 let (cli, user) = setup_user_auth().await; 485 let (user2, auth2) = user_auth(&cli, "wehee", "who@cares.com", "12").await; 486 let group = make_group(&cli, "test1").await; 487 add_group_member(&cli, group.id, user2.id).await; 488 489 let resp = cli.delete(format!("/api/user/groups?gid={}", group.id)) 490 .header::<&str, &str>("Authorization", &auth2).send().await; 491 resp.assert_status_is_ok(); 492 493 let members = find_group(&cli, group.id).await.members; 494 assert!(contents_eq(members, vec![user.id])); 495 }