From 32d8ccf6dab39fe27e50811c5fa5d2e50c92658c Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Mon, 21 Oct 2024 23:42:03 +0200 Subject: [PATCH 1/2] tests/util/test_app: Implement `async_db()` fn --- src/tests/util/test_app.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tests/util/test_app.rs b/src/tests/util/test_app.rs index 86315d40a8f..a0e31281b4b 100644 --- a/src/tests/util/test_app.rs +++ b/src/tests/util/test_app.rs @@ -19,10 +19,12 @@ use crates_io_test_db::TestDatabase; use crates_io_worker::Runner; use diesel::r2d2::{ConnectionManager, PooledConnection}; use diesel::PgConnection; +use diesel_async::AsyncPgConnection; use futures_util::TryStreamExt; use oauth2::{ClientId, ClientSecret}; use regex::Regex; use std::collections::HashSet; +use std::ops::DerefMut; use std::sync::LazyLock; use std::{rc::Rc, sync::Arc, time::Duration}; use tokio::runtime::Handle; @@ -114,6 +116,12 @@ impl TestApp { self.0.test_database.connect() } + /// Obtain an async database connection from the primary database pool. + pub async fn async_db_conn(&self) -> impl DerefMut { + let result = self.as_inner().primary_database.get().await; + result.expect("Failed to get database connection") + } + /// Create a new user with a verified email address in the database /// (`@example.com`) and return a mock user session. /// From 7a003c5a1cd8fdab5f13cb5a64b8995456fcd4f4 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Tue, 22 Oct 2024 19:43:06 +0200 Subject: [PATCH 2/2] tests: Use `async_db_conn()` instead of `db_conn()` where possible --- src/tests/account_lock.rs | 12 ++- src/tests/github_secret_scanning.rs | 97 ++++++++++++------- src/tests/krate/publish/auth.rs | 6 +- src/tests/krate/publish/basics.rs | 6 +- src/tests/krate/publish/categories.rs | 6 +- src/tests/krate/publish/emails.rs | 11 ++- src/tests/krate/publish/rate_limit.rs | 15 ++- src/tests/krate/publish/timestamps.rs | 6 +- src/tests/krate/yanking.rs | 9 +- src/tests/routes/categories/list.rs | 6 +- src/tests/routes/category_slugs/list.rs | 6 +- .../routes/crates/versions/yank_unyank.rs | 57 +++++------ src/tests/routes/me/tokens/create.rs | 34 ++++--- src/tests/routes/me/tokens/delete.rs | 35 ++++--- src/tests/routes/me/tokens/delete_current.rs | 49 ++++++---- src/tests/token.rs | 12 ++- src/tests/worker/git.rs | 23 ++++- src/tests/worker/rss/sync_crate_feed.rs | 37 ++++--- src/tests/worker/rss/sync_crates_feed.rs | 38 ++++---- src/tests/worker/rss/sync_updates_feed.rs | 45 ++++----- src/tests/worker/sync_admins.rs | 47 ++++++--- 21 files changed, 342 insertions(+), 215 deletions(-) diff --git a/src/tests/account_lock.rs b/src/tests/account_lock.rs index 97516e840c3..13fbf2cbcfc 100644 --- a/src/tests/account_lock.rs +++ b/src/tests/account_lock.rs @@ -6,11 +6,12 @@ use insta::assert_snapshot; const URL: &str = "/api/v1/me"; const LOCK_REASON: &str = "test lock reason"; -fn lock_account(app: &TestApp, user_id: i32, until: Option) { +async fn lock_account(app: &TestApp, user_id: i32, until: Option) { use crate::schema::users; use diesel::prelude::*; + use diesel_async::RunQueryDsl; - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; diesel::update(users::table) .set(( @@ -19,13 +20,14 @@ fn lock_account(app: &TestApp, user_id: i32, until: Option) { )) .filter(users::id.eq(user_id)) .execute(&mut conn) + .await .unwrap(); } #[tokio::test(flavor = "multi_thread")] async fn account_locked_indefinitely() { let (app, _anon, user) = TestApp::init().with_user(); - lock_account(&app, user.as_model().id, None); + lock_account(&app, user.as_model().id, None).await; let response = user.get::<()>(URL).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); @@ -40,7 +42,7 @@ async fn account_locked_with_future_expiry() { .naive_utc(); let (app, _anon, user) = TestApp::init().with_user(); - lock_account(&app, user.as_model().id, Some(until)); + lock_account(&app, user.as_model().id, Some(until)).await; let response = user.get::<()>(URL).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); @@ -52,7 +54,7 @@ async fn expired_account_lock() { let until = Utc::now().naive_utc() - Duration::days(1); let (app, _anon, user) = TestApp::init().with_user(); - lock_account(&app, user.as_model().id, Some(until)); + lock_account(&app, user.as_model().id, Some(until)).await; user.get::(URL).await.good(); } diff --git a/src/tests/github_secret_scanning.rs b/src/tests/github_secret_scanning.rs index 3968c200a6b..e6f73411323 100644 --- a/src/tests/github_secret_scanning.rs +++ b/src/tests/github_secret_scanning.rs @@ -3,6 +3,7 @@ use crate::tests::{RequestHelper, TestApp}; use crate::util::token::HashedToken; use crate::{models::ApiToken, schema::api_tokens}; use diesel::prelude::*; +use diesel_async::RunQueryDsl; use googletest::prelude::*; use http::StatusCode; use insta::{assert_json_snapshot, assert_snapshot}; @@ -19,16 +20,19 @@ static GITHUB_PUBLIC_KEY_SIGNATURE: &str = "MEUCIFLZzeK++IhS+y276SRk2Pe5LfDrfvTX #[tokio::test(flavor = "multi_thread")] async fn github_secret_alert_revokes_token() { let (app, anon, user, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Ensure no emails were sent up to this point assert_eq!(app.emails().len(), 0); // Ensure that the token currently exists in the database - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); assert_eq!(tokens[0].name, token.as_model().name); @@ -37,6 +41,7 @@ async fn github_secret_alert_revokes_token() { diesel::update(api_tokens::table) .set(api_tokens::token.eq(hashed_token)) .execute(&mut conn) + .await .unwrap(); let mut request = anon.post_request(URL); @@ -48,16 +53,22 @@ async fn github_secret_alert_revokes_token() { assert_json_snapshot!(response.json()); // Ensure that the token was revoked - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_that!(tokens, empty()); - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(true)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(true)) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); // Ensure exactly one email was sent @@ -67,16 +78,19 @@ async fn github_secret_alert_revokes_token() { #[tokio::test(flavor = "multi_thread")] async fn github_secret_alert_for_revoked_token() { let (app, anon, user, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Ensure no emails were sent up to this point assert_eq!(app.emails().len(), 0); // Ensure that the token currently exists in the database - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); assert_eq!(tokens[0].name, token.as_model().name); @@ -88,6 +102,7 @@ async fn github_secret_alert_for_revoked_token() { api_tokens::revoked.eq(true), )) .execute(&mut conn) + .await .unwrap(); let mut request = anon.post_request(URL); @@ -99,16 +114,22 @@ async fn github_secret_alert_for_revoked_token() { assert_json_snapshot!(response.json()); // Ensure that the token is still revoked - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_that!(tokens, empty()); - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(true)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(true)) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); // Ensure still no emails were sent @@ -118,16 +139,19 @@ async fn github_secret_alert_for_revoked_token() { #[tokio::test(flavor = "multi_thread")] async fn github_secret_alert_for_unknown_token() { let (app, anon, user, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Ensure no emails were sent up to this point assert_eq!(app.emails().len(), 0); // Ensure that the token currently exists in the database - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); assert_eq!(tokens[0].name, token.as_model().name); @@ -140,10 +164,13 @@ async fn github_secret_alert_for_unknown_token() { assert_json_snapshot!(response.json()); // Ensure that the token was not revoked - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); assert_eq!(tokens[0].name, token.as_model().name); diff --git a/src/tests/krate/publish/auth.rs b/src/tests/krate/publish/auth.rs index f35abd12c97..c37ab6eda1d 100644 --- a/src/tests/krate/publish/auth.rs +++ b/src/tests/krate/publish/auth.rs @@ -1,7 +1,8 @@ use crate::schema::api_tokens; use crate::tests::builders::{CrateBuilder, PublishBuilder}; use crate::tests::util::{RequestHelper, TestApp}; -use diesel::{ExpressionMethods, RunQueryDsl}; +use diesel::ExpressionMethods; +use diesel_async::RunQueryDsl; use googletest::prelude::*; use http::StatusCode; use insta::assert_snapshot; @@ -9,7 +10,7 @@ use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn new_wrong_token() { let (app, anon, _, token) = TestApp::full().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Try to publish without a token let crate_to_publish = PublishBuilder::new("foo", "1.0.0"); @@ -21,6 +22,7 @@ async fn new_wrong_token() { diesel::update(api_tokens::table) .set(api_tokens::token.eq(b"bad" as &[u8])) .execute(&mut conn) + .await .unwrap(); let crate_to_publish = PublishBuilder::new("foo", "1.0.0"); diff --git a/src/tests/krate/publish/basics.rs b/src/tests/krate/publish/basics.rs index 46f2690fe65..3181230656c 100644 --- a/src/tests/krate/publish/basics.rs +++ b/src/tests/krate/publish/basics.rs @@ -1,7 +1,8 @@ use crate::schema::versions_published_by; use crate::tests::builders::{CrateBuilder, PublishBuilder}; use crate::tests::util::{RequestHelper, TestApp}; -use diesel::{QueryDsl, RunQueryDsl}; +use diesel::QueryDsl; +use diesel_async::RunQueryDsl; use googletest::prelude::*; use http::StatusCode; use insta::{assert_json_snapshot, assert_snapshot}; @@ -9,7 +10,7 @@ use insta::{assert_json_snapshot, assert_snapshot}; #[tokio::test(flavor = "multi_thread")] async fn new_krate() { let (app, _, user) = TestApp::full().with_user(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let crate_to_publish = PublishBuilder::new("foo_new", "1.0.0"); let response = user.publish_crate(crate_to_publish).await; @@ -33,6 +34,7 @@ async fn new_krate() { let email: String = versions_published_by::table .select(versions_published_by::email) .first(&mut conn) + .await .unwrap(); assert_eq!(email, "foo@example.com"); diff --git a/src/tests/krate/publish/categories.rs b/src/tests/krate/publish/categories.rs index 7df137dc603..c89d271eb7c 100644 --- a/src/tests/krate/publish/categories.rs +++ b/src/tests/krate/publish/categories.rs @@ -2,7 +2,8 @@ use crate::tests::builders::PublishBuilder; use crate::tests::new_category; use crate::tests::util::{RequestHelper, TestApp}; use crates_io_database::schema::categories; -use diesel::{insert_into, RunQueryDsl}; +use diesel::insert_into; +use diesel_async::RunQueryDsl; use googletest::prelude::*; use http::StatusCode; use insta::{assert_json_snapshot, assert_snapshot}; @@ -10,11 +11,12 @@ use insta::{assert_json_snapshot, assert_snapshot}; #[tokio::test(flavor = "multi_thread")] async fn good_categories() { let (app, _, _, token) = TestApp::full().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; insert_into(categories::table) .values(new_category("Category 1", "cat1", "Category 1 crates")) .execute(&mut conn) + .await .unwrap(); let crate_to_publish = PublishBuilder::new("foo_good_cat", "1.0.0").category("cat1"); diff --git a/src/tests/krate/publish/emails.rs b/src/tests/krate/publish/emails.rs index 2186ae317b4..b0503865a58 100644 --- a/src/tests/krate/publish/emails.rs +++ b/src/tests/krate/publish/emails.rs @@ -1,17 +1,19 @@ use crate::schema::emails; use crate::tests::builders::PublishBuilder; use crate::tests::util::{RequestHelper, TestApp}; -use diesel::{delete, update, ExpressionMethods, RunQueryDsl}; +use diesel::{delete, update, ExpressionMethods}; +use diesel_async::RunQueryDsl; use googletest::prelude::*; + use http::StatusCode; use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn new_krate_without_any_email_fails() { let (app, _, _, token) = TestApp::full().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; - delete(emails::table).execute(&mut conn).unwrap(); + delete(emails::table).execute(&mut conn).await.unwrap(); let crate_to_publish = PublishBuilder::new("foo_no_email", "1.0.0"); @@ -25,11 +27,12 @@ async fn new_krate_without_any_email_fails() { #[tokio::test(flavor = "multi_thread")] async fn new_krate_with_unverified_email_fails() { let (app, _, _, token) = TestApp::full().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; update(emails::table) .set((emails::verified.eq(false),)) .execute(&mut conn) + .await .unwrap(); let crate_to_publish = PublishBuilder::new("foo_unverified_email", "1.0.0"); diff --git a/src/tests/krate/publish/rate_limit.rs b/src/tests/krate/publish/rate_limit.rs index 2ee67604111..8fda88b69e5 100644 --- a/src/tests/krate/publish/rate_limit.rs +++ b/src/tests/krate/publish/rate_limit.rs @@ -3,7 +3,8 @@ use crate::schema::{publish_limit_buckets, publish_rate_overrides}; use crate::tests::builders::PublishBuilder; use crate::tests::util::{RequestHelper, TestApp}; use chrono::{NaiveDateTime, Utc}; -use diesel::{ExpressionMethods, RunQueryDsl}; +use diesel::ExpressionMethods; +use diesel_async::RunQueryDsl; use http::StatusCode; use insta::assert_snapshot; use std::thread; @@ -15,7 +16,7 @@ async fn publish_new_crate_ratelimit_hit() { .with_rate_limit(LimitedAction::PublishNew, Duration::from_millis(500), 1) .with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Set up the database so it'll think we've massively ratelimited ourselves @@ -29,6 +30,7 @@ async fn publish_new_crate_ratelimit_hit() { publish_limit_buckets::last_refill.eq(far_future), )) .execute(&mut conn) + .await .expect("Failed to set fake ratelimit"); let crate_to_publish = PublishBuilder::new("rate_limited", "1.0.0"); @@ -49,7 +51,7 @@ async fn publish_new_crate_ratelimit_expires() { .with_rate_limit(LimitedAction::PublishNew, Duration::from_millis(500), 1) .with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Set up the database so it'll think we've massively ratelimited ourselves @@ -63,6 +65,7 @@ async fn publish_new_crate_ratelimit_expires() { publish_limit_buckets::last_refill.eq(just_now), )) .execute(&mut conn) + .await .expect("Failed to set fake ratelimit"); let crate_to_publish = PublishBuilder::new("rate_limited", "1.0.0"); @@ -91,7 +94,7 @@ async fn publish_new_crate_override_loosens_ratelimit() { ) .with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Add an override so our user gets *2* new tokens (expires, y'know, sometime) diesel::insert_into(publish_rate_overrides::table) @@ -102,6 +105,7 @@ async fn publish_new_crate_override_loosens_ratelimit() { publish_rate_overrides::action.eq(LimitedAction::PublishNew), )) .execute(&mut conn) + .await .expect("Failed to add ratelimit override"); let crate_to_publish = PublishBuilder::new("rate_limited1", "1.0.0"); @@ -167,7 +171,7 @@ async fn publish_new_crate_expired_override_ignored() { ) .with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Add an override so our user gets *2* new tokens (expires, y'know, sometime) let just_now = Utc::now().naive_utc() - Duration::from_secs(1); @@ -179,6 +183,7 @@ async fn publish_new_crate_expired_override_ignored() { publish_rate_overrides::action.eq(LimitedAction::PublishNew), )) .execute(&mut conn) + .await .expect("Failed to add ratelimit override"); let crate_to_publish = PublishBuilder::new("rate_limited1", "1.0.0"); diff --git a/src/tests/krate/publish/timestamps.rs b/src/tests/krate/publish/timestamps.rs index 70c6b9b9179..57533d13bb3 100644 --- a/src/tests/krate/publish/timestamps.rs +++ b/src/tests/krate/publish/timestamps.rs @@ -5,10 +5,11 @@ async fn uploading_new_version_touches_crate() { use crate::tests::util::{RequestHelper, TestApp}; use crate::tests::CrateResponse; use diesel::dsl::*; - use diesel::{ExpressionMethods, RunQueryDsl}; + use diesel::ExpressionMethods; + use diesel_async::RunQueryDsl; let (app, _, user) = TestApp::full().with_user(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let crate_to_publish = PublishBuilder::new("foo_versions_updated_at", "1.0.0"); user.publish_crate(crate_to_publish).await.good(); @@ -16,6 +17,7 @@ async fn uploading_new_version_touches_crate() { diesel::update(crates::table) .set(crates::updated_at.eq(crates::updated_at - 1.hour())) .execute(&mut conn) + .await .unwrap(); let json: CrateResponse = user.show_crate("foo_versions_updated_at").await; diff --git a/src/tests/krate/yanking.rs b/src/tests/krate/yanking.rs index 3d1680ffe33..764d89f30cb 100644 --- a/src/tests/krate/yanking.rs +++ b/src/tests/krate/yanking.rs @@ -5,7 +5,8 @@ use crate::tests::routes::crates::versions::yank_unyank::YankRequestHelper; use crate::tests::util::{RequestHelper, TestApp}; use crate::tests::VersionResponse; use chrono::Utc; -use diesel::{ExpressionMethods, RunQueryDsl}; +use diesel::ExpressionMethods; +use diesel_async::RunQueryDsl; use googletest::prelude::*; use http::StatusCode; use insta::{assert_json_snapshot, assert_snapshot}; @@ -82,7 +83,7 @@ async fn yank_ratelimit_hit() { .with_rate_limit(LimitedAction::YankUnyank, Duration::from_millis(500), 1) .with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Set up the database so it'll think we've massively rate-limited ourselves. @@ -96,6 +97,7 @@ async fn yank_ratelimit_hit() { publish_limit_buckets::last_refill.eq(far_future), )) .execute(&mut conn) + .await .expect("Failed to set fake ratelimit"); // Upload a new crate @@ -117,7 +119,7 @@ async fn yank_ratelimit_expires() { .with_rate_limit(LimitedAction::YankUnyank, Duration::from_millis(500), 1) .with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Set up the database so it'll think we've massively ratelimited ourselves @@ -131,6 +133,7 @@ async fn yank_ratelimit_expires() { publish_limit_buckets::last_refill.eq(just_now), )) .execute(&mut conn) + .await .expect("Failed to set fake ratelimit"); // Upload a new crate diff --git a/src/tests/routes/categories/list.rs b/src/tests/routes/categories/list.rs index eec4ba33fb2..f3d60d3c312 100644 --- a/src/tests/routes/categories/list.rs +++ b/src/tests/routes/categories/list.rs @@ -1,14 +1,15 @@ use crate::tests::new_category; use crate::tests::util::{RequestHelper, TestApp}; use crates_io_database::schema::categories; -use diesel::{insert_into, RunQueryDsl}; +use diesel::insert_into; +use diesel_async::RunQueryDsl; use insta::assert_json_snapshot; use serde_json::Value; #[tokio::test(flavor = "multi_thread")] async fn index() { let (app, anon) = TestApp::init().empty(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // List 0 categories if none exist let json: Value = anon.get("/api/v1/categories").await.good(); @@ -23,6 +24,7 @@ async fn index() { insert_into(categories::table) .values(cats) .execute(&mut conn) + .await .unwrap(); // Only the top-level categories should be on the page diff --git a/src/tests/routes/category_slugs/list.rs b/src/tests/routes/category_slugs/list.rs index 34e140135b2..b62926c0e4c 100644 --- a/src/tests/routes/category_slugs/list.rs +++ b/src/tests/routes/category_slugs/list.rs @@ -1,14 +1,15 @@ use crate::tests::new_category; use crate::tests::util::{RequestHelper, TestApp}; use crates_io_database::schema::categories; -use diesel::{insert_into, RunQueryDsl}; +use diesel::insert_into; +use diesel_async::RunQueryDsl; use insta::assert_json_snapshot; use serde_json::Value; #[tokio::test(flavor = "multi_thread")] async fn category_slugs_returns_all_slugs_in_alphabetical_order() { let (app, anon) = TestApp::init().empty(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let cats = vec![ new_category("Foo", "foo", "For crates that foo"), @@ -18,6 +19,7 @@ async fn category_slugs_returns_all_slugs_in_alphabetical_order() { insert_into(categories::table) .values(cats) .execute(&mut conn) + .await .unwrap(); let response: Value = anon.get("/api/v1/category_slugs").await.good(); diff --git a/src/tests/routes/crates/versions/yank_unyank.rs b/src/tests/routes/crates/versions/yank_unyank.rs index e55f98c4f23..988a217d169 100644 --- a/src/tests/routes/crates/versions/yank_unyank.rs +++ b/src/tests/routes/crates/versions/yank_unyank.rs @@ -129,6 +129,7 @@ mod auth { use crate::tests::util::{MockAnonymousUser, MockCookieUser}; use chrono::{Duration, Utc}; use diesel::prelude::*; + use diesel_async::RunQueryDsl; use insta::assert_snapshot; const CRATE_NAME: &str = "fyk"; @@ -143,8 +144,8 @@ mod auth { (app, anon, cookie) } - fn is_yanked(app: &TestApp) -> bool { - let mut conn = app.db_conn(); + async fn is_yanked(app: &TestApp) -> bool { + let mut conn = app.async_db_conn().await; versions::table .inner_join(crates::table) @@ -152,6 +153,7 @@ mod auth { .filter(crates::name.eq(CRATE_NAME)) .filter(versions::num.eq(CRATE_VERSION)) .get_result(&mut conn) + .await .unwrap() } @@ -162,12 +164,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this action requires authentication"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this action requires authentication"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -177,12 +179,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(is_yanked(&app)); + assert!(is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -193,12 +195,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(is_yanked(&app)); + assert!(is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -212,12 +214,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(is_yanked(&app)); + assert!(is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -231,12 +233,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"authentication failed"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"authentication failed"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -248,12 +250,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(is_yanked(&app)); + assert!(is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -269,12 +271,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this token does not have the required permissions to perform this action"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this token does not have the required permissions to perform this action"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -290,12 +292,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(is_yanked(&app)); + assert!(is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -312,12 +314,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(is_yanked(&app)); + assert!(is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -333,12 +335,12 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this token does not have the required permissions to perform this action"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this token does not have the required permissions to perform this action"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] @@ -354,34 +356,35 @@ mod auth { let response = client.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this token does not have the required permissions to perform this action"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); let response = client.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"this token does not have the required permissions to perform this action"}]}"###); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } #[tokio::test(flavor = "multi_thread")] async fn admin() { let (app, _, _) = prepare().await; - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let admin = app.db_new_user("admin"); diesel::update(admin.as_model()) .set(users::is_admin.eq(true)) .execute(&mut conn) + .await .unwrap(); let response = admin.yank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(is_yanked(&app)); + assert!(is_yanked(&app).await); let response = admin.unyank(CRATE_NAME, CRATE_VERSION).await; assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.json(), json!({ "ok": true })); - assert!(!is_yanked(&app)); + assert!(!is_yanked(&app).await); } } diff --git a/src/tests/routes/me/tokens/create.rs b/src/tests/routes/me/tokens/create.rs index 105fc48af4b..d302d09bd6a 100644 --- a/src/tests/routes/me/tokens/create.rs +++ b/src/tests/routes/me/tokens/create.rs @@ -3,6 +3,7 @@ use crate::models::ApiToken; use crate::tests::util::insta::{self, assert_json_snapshot}; use crate::tests::util::{RequestHelper, TestApp}; use diesel::prelude::*; +use diesel_async::RunQueryDsl; use googletest::prelude::*; use http::StatusCode; use insta::assert_snapshot; @@ -57,7 +58,7 @@ async fn create_token_exceeded_tokens_per_user() { #[tokio::test(flavor = "multi_thread")] async fn create_token_success() { let (app, _, user) = TestApp::init().with_user(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let response = user.put::<()>("/api/v1/me/tokens", NEW_BAR).await; assert_eq!(response.status(), StatusCode::OK); @@ -68,9 +69,12 @@ async fn create_token_success() { ".api_token.token" => insta::api_token_redaction(), }); - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); assert_eq!(tokens[0].name, "bar"); @@ -120,7 +124,7 @@ async fn cannot_create_token_with_token() { #[tokio::test(flavor = "multi_thread")] async fn create_token_with_scopes() { let (app, _, user) = TestApp::init().with_user(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let json = json!({ "api_token": { @@ -141,9 +145,12 @@ async fn create_token_with_scopes() { ".api_token.token" => insta::api_token_redaction(), }); - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); assert_eq!(tokens[0].name, "bar"); @@ -167,7 +174,7 @@ async fn create_token_with_scopes() { #[tokio::test(flavor = "multi_thread")] async fn create_token_with_null_scopes() { let (app, _, user) = TestApp::init().with_user(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let json = json!({ "api_token": { @@ -188,9 +195,12 @@ async fn create_token_with_null_scopes() { ".api_token.token" => insta::api_token_redaction(), }); - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .load(&mut conn) + .await + ); assert_that!(tokens, len(eq(1))); assert_eq!(tokens[0].name, "bar"); diff --git a/src/tests/routes/me/tokens/delete.rs b/src/tests/routes/me/tokens/delete.rs index 280ebb7c3e6..6051ced4491 100644 --- a/src/tests/routes/me/tokens/delete.rs +++ b/src/tests/routes/me/tokens/delete.rs @@ -2,6 +2,7 @@ use crate::models::ApiToken; use crate::schema::api_tokens; use crate::tests::util::{RequestHelper, TestApp}; use diesel::prelude::*; +use diesel_async::RunQueryDsl; #[derive(Deserialize)] pub struct RevokedResponse {} @@ -15,15 +16,18 @@ async fn revoke_token_non_existing() { #[tokio::test(flavor = "multi_thread")] async fn revoke_token_doesnt_revoke_other_users_token() { let (app, _, user1, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let user1 = user1.as_model(); let token = token.as_model(); let user2 = app.db_new_user("baz"); // List tokens for first user contains the token - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user1) - .select(ApiToken::as_select()) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user1) + .select(ApiToken::as_select()) + .load(&mut conn) + .await + ); assert_eq!(tokens.len(), 1); assert_eq!(tokens[0].name, token.name); @@ -34,9 +38,12 @@ async fn revoke_token_doesnt_revoke_other_users_token() { .good(); // List tokens for first user still contains the token - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user1) - .select(ApiToken::as_select()) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user1) + .select(ApiToken::as_select()) + .load(&mut conn) + .await + ); assert_eq!(tokens.len(), 1); assert_eq!(tokens[0].name, token.name); } @@ -44,12 +51,15 @@ async fn revoke_token_doesnt_revoke_other_users_token() { #[tokio::test(flavor = "multi_thread")] async fn revoke_token_success() { let (app, _, user, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // List tokens contains the token - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .load(&mut conn) + .await + ); assert_eq!(tokens.len(), 1); assert_eq!(tokens[0].name, token.as_model().name); @@ -63,6 +73,7 @@ async fn revoke_token_success() { let count = ApiToken::belonging_to(user.as_model()) .filter(api_tokens::revoked.eq(false)) .count() - .get_result(&mut conn); + .get_result(&mut conn) + .await; assert_eq!(count, Ok(0)); } diff --git a/src/tests/routes/me/tokens/delete_current.rs b/src/tests/routes/me/tokens/delete_current.rs index f14896a4a5f..c5774645e94 100644 --- a/src/tests/routes/me/tokens/delete_current.rs +++ b/src/tests/routes/me/tokens/delete_current.rs @@ -2,20 +2,24 @@ use crate::models::ApiToken; use crate::schema::api_tokens; use crate::tests::util::{RequestHelper, TestApp}; use diesel::prelude::*; +use diesel_async::RunQueryDsl; use http::StatusCode; use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn revoke_current_token_success() { let (app, _, user, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Ensure that the token currently exists in the database - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_eq!(tokens.len(), 1); assert_eq!(tokens[0].name, token.as_model().name); @@ -25,10 +29,13 @@ async fn revoke_current_token_success() { // Ensure that the token was removed from the database - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_eq!(tokens.len(), 0); } @@ -44,14 +51,17 @@ async fn revoke_current_token_without_auth() { #[tokio::test(flavor = "multi_thread")] async fn revoke_current_token_with_cookie_user() { let (app, _, user, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; // Ensure that the token currently exists in the database - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_eq!(tokens.len(), 1); assert_eq!(tokens[0].name, token.as_model().name); @@ -62,9 +72,12 @@ async fn revoke_current_token_with_cookie_user() { // Ensure that the token still exists in the database after the failed request - let tokens: Vec = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .filter(api_tokens::revoked.eq(false)) - .load(&mut conn)); + let tokens: Vec = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .filter(api_tokens::revoked.eq(false)) + .load(&mut conn) + .await + ); assert_eq!(tokens.len(), 1); } diff --git a/src/tests/token.rs b/src/tests/token.rs index 404cd1e2972..73fcb657d6e 100644 --- a/src/tests/token.rs +++ b/src/tests/token.rs @@ -2,6 +2,7 @@ use crate::tests::util::MockRequestExt; use crate::tests::{RequestHelper, TestApp}; use crate::{models::ApiToken, views::EncodableMe}; use diesel::prelude::*; +use diesel_async::RunQueryDsl; use http::{header, StatusCode}; use insta::assert_snapshot; @@ -9,7 +10,7 @@ use insta::assert_snapshot; async fn using_token_updates_last_used_at() { let url = "/api/v1/me"; let (app, anon, user, token) = TestApp::init().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; anon.get(url).await.assert_forbidden(); user.get::(url).await.good(); @@ -18,9 +19,12 @@ async fn using_token_updates_last_used_at() { // Use the token once token.search("following=1").await; - let token: ApiToken = assert_ok!(ApiToken::belonging_to(user.as_model()) - .select(ApiToken::as_select()) - .first(&mut conn)); + let token: ApiToken = assert_ok!( + ApiToken::belonging_to(user.as_model()) + .select(ApiToken::as_select()) + .first(&mut conn) + .await + ); assert_some!(token.last_used_at); // Would check that it updates the timestamp here, but the timestamp is diff --git a/src/tests/worker/git.rs b/src/tests/worker/git.rs index ecf8741e08e..fb2ef7e507e 100644 --- a/src/tests/worker/git.rs +++ b/src/tests/worker/git.rs @@ -4,12 +4,13 @@ use crate::tests::util::{RequestHelper, TestApp}; use crate::worker::jobs; use crates_io_worker::BackgroundJob; use diesel::prelude::*; +use diesel_async::RunQueryDsl; use http::StatusCode; #[tokio::test(flavor = "multi_thread")] async fn index_smoke_test() { let (app, _, _, token) = TestApp::full().with_token(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; let upstream = app.upstream_index(); // Add a new crate @@ -49,11 +50,23 @@ async fn index_smoke_test() { use crate::schema::crates; - let krate: Crate = assert_ok!(Crate::by_name("serde").first(&mut conn)); - assert_ok!(diesel::delete(crates::table.find(krate.id)).execute(&mut conn)); + let krate: Crate = assert_ok!(Crate::by_name("serde").first(&mut conn).await); + assert_ok!( + diesel::delete(crates::table.find(krate.id)) + .execute(&mut conn) + .await + ); - assert_ok!(jobs::SyncToGitIndex::new("serde").enqueue(&mut conn)); - assert_ok!(jobs::SyncToSparseIndex::new("serde").enqueue(&mut conn)); + assert_ok!( + jobs::SyncToGitIndex::new("serde") + .async_enqueue(&mut conn) + .await + ); + assert_ok!( + jobs::SyncToSparseIndex::new("serde") + .async_enqueue(&mut conn) + .await + ); app.run_pending_background_jobs().await; assert_ok_eq!( diff --git a/src/tests/worker/rss/sync_crate_feed.rs b/src/tests/worker/rss/sync_crate_feed.rs index 4371687b0ff..50fed1ce5e8 100644 --- a/src/tests/worker/rss/sync_crate_feed.rs +++ b/src/tests/worker/rss/sync_crate_feed.rs @@ -4,23 +4,23 @@ use crate::worker::jobs; use chrono::DateTime; use crates_io_worker::BackgroundJob; use diesel::prelude::*; -use diesel::{PgConnection, RunQueryDsl}; +use diesel_async::{AsyncPgConnection, RunQueryDsl}; use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn test_sync_crate_feed() { let (app, _) = TestApp::full().empty(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; - create_version(&mut conn, "foo", "0.1.0", "2024-06-20T10:13:54Z"); - create_version(&mut conn, "foo", "0.1.1", "2024-06-20T12:45:12Z"); - create_version(&mut conn, "foo", "1.0.0", "2024-06-21T17:01:33Z"); - create_version(&mut conn, "bar", "3.0.0-beta.1", "2024-06-21T17:03:45Z"); - create_version(&mut conn, "foo", "1.1.0", "2024-06-22T08:30:01Z"); - create_version(&mut conn, "foo", "1.2.0", "2024-06-22T15:57:19Z"); + create_version(&mut conn, "foo", "0.1.0", "2024-06-20T10:13:54Z").await; + create_version(&mut conn, "foo", "0.1.1", "2024-06-20T12:45:12Z").await; + create_version(&mut conn, "foo", "1.0.0", "2024-06-21T17:01:33Z").await; + create_version(&mut conn, "bar", "3.0.0-beta.1", "2024-06-21T17:03:45Z").await; + create_version(&mut conn, "foo", "1.1.0", "2024-06-22T08:30:01Z").await; + create_version(&mut conn, "foo", "1.2.0", "2024-06-22T15:57:19Z").await; let job = jobs::rss::SyncCrateFeed::new("foo".to_string()); - job.enqueue(&mut conn).unwrap(); + job.async_enqueue(&mut conn).await.unwrap(); app.run_pending_background_jobs().await; @@ -33,7 +33,12 @@ async fn test_sync_crate_feed() { assert_snapshot!(content); } -fn create_version(conn: &mut PgConnection, name: &str, version: &str, publish_time: &str) -> i32 { +async fn create_version( + conn: &mut AsyncPgConnection, + name: &str, + version: &str, + publish_time: &str, +) -> i32 { let publish_time = DateTime::parse_from_rfc3339(publish_time) .unwrap() .naive_utc(); @@ -42,11 +47,13 @@ fn create_version(conn: &mut PgConnection, name: &str, version: &str, publish_ti .select(crates::id) .filter(crates::name.eq(name)) .get_result::(conn) + .await .optional() .unwrap(); - let crate_id = crate_id.unwrap_or_else(|| { - diesel::insert_into(crates::table) + let crate_id = match crate_id { + Some(crate_id) => crate_id, + None => diesel::insert_into(crates::table) .values(( crates::name.eq(name), crates::created_at.eq(publish_time), @@ -54,8 +61,9 @@ fn create_version(conn: &mut PgConnection, name: &str, version: &str, publish_ti )) .returning(crates::id) .get_result(conn) - .unwrap() - }); + .await + .unwrap(), + }; diesel::insert_into(versions::table) .values(( @@ -67,5 +75,6 @@ fn create_version(conn: &mut PgConnection, name: &str, version: &str, publish_ti )) .returning(versions::id) .get_result(conn) + .await .unwrap() } diff --git a/src/tests/worker/rss/sync_crates_feed.rs b/src/tests/worker/rss/sync_crates_feed.rs index dfe01fe424e..baeff61554d 100644 --- a/src/tests/worker/rss/sync_crates_feed.rs +++ b/src/tests/worker/rss/sync_crates_feed.rs @@ -4,30 +4,25 @@ use crate::worker::jobs; use chrono::DateTime; use crates_io_worker::BackgroundJob; use diesel::prelude::*; -use diesel::{PgConnection, RunQueryDsl}; +use diesel_async::{AsyncPgConnection, RunQueryDsl}; use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn test_sync_crates_feed() { let (app, _) = TestApp::full().empty(); - let mut conn = app.db_conn(); - - create_crate( - &mut conn, - "foo", - Some("something something foo"), - "2024-06-20T10:13:54Z", - ); - create_crate(&mut conn, "bar", None, "2024-06-20T12:45:12Z"); - create_crate( - &mut conn, - "baz", - Some("does it handle XML? "), - "2024-06-21T17:01:33Z", - ); - create_crate(&mut conn, "quux", None, "2024-06-21T17:03:45Z"); - - jobs::rss::SyncCratesFeed.enqueue(&mut conn).unwrap(); + let mut conn = app.async_db_conn().await; + + let description = Some("something something foo"); + create_crate(&mut conn, "foo", description, "2024-06-20T10:13:54Z").await; + create_crate(&mut conn, "bar", None, "2024-06-20T12:45:12Z").await; + let description = Some("does it handle XML? "); + create_crate(&mut conn, "baz", description, "2024-06-21T17:01:33Z").await; + create_crate(&mut conn, "quux", None, "2024-06-21T17:03:45Z").await; + + jobs::rss::SyncCratesFeed + .async_enqueue(&mut conn) + .await + .unwrap(); app.run_pending_background_jobs().await; @@ -40,8 +35,8 @@ async fn test_sync_crates_feed() { assert_snapshot!(content); } -fn create_crate( - conn: &mut PgConnection, +async fn create_crate( + conn: &mut AsyncPgConnection, name: &str, description: Option<&str>, publish_time: &str, @@ -58,5 +53,6 @@ fn create_crate( crates::updated_at.eq(publish_time), )) .execute(conn) + .await .unwrap(); } diff --git a/src/tests/worker/rss/sync_updates_feed.rs b/src/tests/worker/rss/sync_updates_feed.rs index dc182bbb0d3..1c56288338c 100644 --- a/src/tests/worker/rss/sync_updates_feed.rs +++ b/src/tests/worker/rss/sync_updates_feed.rs @@ -4,30 +4,27 @@ use crate::worker::jobs; use chrono::DateTime; use crates_io_worker::BackgroundJob; use diesel::prelude::*; -use diesel::{PgConnection, RunQueryDsl}; +use diesel_async::{AsyncPgConnection, RunQueryDsl}; use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn test_sync_updates_feed() { let (app, _) = TestApp::full().empty(); - let mut conn = app.db_conn(); + let mut conn = app.async_db_conn().await; - let d = "let's try & break this "; + let d = Some("let's try & break this "); - create_version(&mut conn, "foo", "0.1.0", None, "2024-06-20T10:13:54Z"); - create_version(&mut conn, "foo", "0.1.1", None, "2024-06-20T12:45:12Z"); - create_version(&mut conn, "foo", "1.0.0", None, "2024-06-21T17:01:33Z"); - create_version( - &mut conn, - "bar", - "3.0.0-beta.1", - Some(d), - "2024-06-21T17:03:45Z", - ); - create_version(&mut conn, "foo", "1.1.0", None, "2024-06-22T08:30:01Z"); - create_version(&mut conn, "foo", "1.2.0", None, "2024-06-22T15:57:19Z"); + create_version(&mut conn, "foo", "0.1.0", None, "2024-06-20T10:13:54Z").await; + create_version(&mut conn, "foo", "0.1.1", None, "2024-06-20T12:45:12Z").await; + create_version(&mut conn, "foo", "1.0.0", None, "2024-06-21T17:01:33Z").await; + create_version(&mut conn, "bar", "3.0.0-beta.1", d, "2024-06-21T17:03:45Z").await; + create_version(&mut conn, "foo", "1.1.0", None, "2024-06-22T08:30:01Z").await; + create_version(&mut conn, "foo", "1.2.0", None, "2024-06-22T15:57:19Z").await; - jobs::rss::SyncUpdatesFeed.enqueue(&mut conn).unwrap(); + jobs::rss::SyncUpdatesFeed + .async_enqueue(&mut conn) + .await + .unwrap(); app.run_pending_background_jobs().await; @@ -40,8 +37,8 @@ async fn test_sync_updates_feed() { assert_snapshot!(content); } -fn create_version( - conn: &mut PgConnection, +async fn create_version( + conn: &mut AsyncPgConnection, name: &str, version: &str, description: Option<&str>, @@ -55,11 +52,13 @@ fn create_version( .select(crates::id) .filter(crates::name.eq(name)) .get_result::(conn) + .await .optional() .unwrap(); - let crate_id = crate_id.unwrap_or_else(|| { - diesel::insert_into(crates::table) + let crate_id = match crate_id { + Some(crate_id) => crate_id, + None => diesel::insert_into(crates::table) .values(( crates::name.eq(name), crates::description.eq(description), @@ -68,8 +67,9 @@ fn create_version( )) .returning(crates::id) .get_result(conn) - .unwrap() - }); + .await + .unwrap(), + }; diesel::insert_into(versions::table) .values(( @@ -81,5 +81,6 @@ fn create_version( )) .returning(versions::id) .get_result(conn) + .await .unwrap() } diff --git a/src/tests/worker/sync_admins.rs b/src/tests/worker/sync_admins.rs index 39b8000d578..4add33bd49b 100644 --- a/src/tests/worker/sync_admins.rs +++ b/src/tests/worker/sync_admins.rs @@ -4,7 +4,8 @@ use crate::worker::jobs::SyncAdmins; use crates_io_team_repo::{MockTeamRepo, Permission, Person}; use crates_io_worker::BackgroundJob; use diesel::prelude::*; -use diesel::{PgConnection, QueryResult, RunQueryDsl}; +use diesel::QueryResult; +use diesel_async::{AsyncPgConnection, RunQueryDsl}; use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] @@ -22,21 +23,27 @@ async fn test_sync_admins_job() { .returning(move |_| Ok(mock_response.clone())); let (app, _) = TestApp::full().with_team_repo(team_repo).empty(); - let mut conn = app.db_conn(); - - create_user("existing-admin", 1, true, &mut conn).unwrap(); - create_user("obsolete-admin", 2, true, &mut conn).unwrap(); - create_user("new-admin", 3, false, &mut conn).unwrap(); - create_user("unrelated-user", 42, false, &mut conn).unwrap(); - - let admins = get_admins(&mut conn).unwrap(); + let mut conn = app.async_db_conn().await; + + create_user("existing-admin", 1, true, &mut conn) + .await + .unwrap(); + create_user("obsolete-admin", 2, true, &mut conn) + .await + .unwrap(); + create_user("new-admin", 3, false, &mut conn).await.unwrap(); + create_user("unrelated-user", 42, false, &mut conn) + .await + .unwrap(); + + let admins = get_admins(&mut conn).await.unwrap(); let expected_admins = vec![("existing-admin".into(), 1), ("obsolete-admin".into(), 2)]; assert_eq!(admins, expected_admins); - SyncAdmins.enqueue(&mut conn).unwrap(); + SyncAdmins.async_enqueue(&mut conn).await.unwrap(); app.run_pending_background_jobs().await; - let admins = get_admins(&mut conn).unwrap(); + let admins = get_admins(&mut conn).await.unwrap(); let expected_admins = vec![("existing-admin".into(), 1), ("new-admin".into(), 3)]; assert_eq!(admins, expected_admins); @@ -44,7 +51,7 @@ async fn test_sync_admins_job() { // Run the job again to verify that no new emails are sent // for `new-admin-without-account`. - SyncAdmins.enqueue(&mut conn).unwrap(); + SyncAdmins.async_enqueue(&mut conn).await.unwrap(); app.run_pending_background_jobs().await; assert_eq!(app.emails().len(), 2); @@ -64,7 +71,12 @@ fn mock_person(name: impl Into, github_id: i32) -> Person { } } -fn create_user(name: &str, gh_id: i32, is_admin: bool, conn: &mut PgConnection) -> QueryResult<()> { +async fn create_user( + name: &str, + gh_id: i32, + is_admin: bool, + conn: &mut AsyncPgConnection, +) -> QueryResult<()> { let user_id = diesel::insert_into(users::table) .values(( users::name.eq(name), @@ -74,7 +86,8 @@ fn create_user(name: &str, gh_id: i32, is_admin: bool, conn: &mut PgConnection) users::is_admin.eq(is_admin), )) .returning(users::id) - .get_result::(conn)?; + .get_result::(conn) + .await?; diesel::insert_into(emails::table) .values(( @@ -82,15 +95,17 @@ fn create_user(name: &str, gh_id: i32, is_admin: bool, conn: &mut PgConnection) emails::email.eq(format!("{}@crates.io", name)), emails::verified.eq(true), )) - .execute(conn)?; + .execute(conn) + .await?; Ok(()) } -fn get_admins(conn: &mut PgConnection) -> QueryResult> { +async fn get_admins(conn: &mut AsyncPgConnection) -> QueryResult> { users::table .select((users::gh_login, users::gh_id)) .filter(users::is_admin.eq(true)) .order(users::gh_id.asc()) .get_results(conn) + .await }