diff --git a/src/badge.rs b/src/badge.rs index 34e48536859..97c7b2d6eaa 100644 --- a/src/badge.rs +++ b/src/badge.rs @@ -1,12 +1,9 @@ -use Model; use krate::Crate; use schema::badges; use util::CargoResult; use diesel::pg::{Pg, PgConnection}; use diesel::prelude::*; -use pg::GenericConnection; -use pg::rows::Row; use serde_json; use std::collections::HashMap; @@ -43,17 +40,6 @@ impl Queryable for Badge { } } -impl Model for Badge { - fn from_row(row: &Row) -> Badge { - let badge_type: String = row.get("badge_type"); - let attributes: serde_json::Value = row.get("attributes"); - let json = json!({"badge_type": badge_type, "attributes": attributes}); - serde_json::from_value(json) - .expect("Invalid CI badge in the database") - } - fn table_name(_: Option) -> &'static str { "badges" } -} - impl Badge { pub fn encodable(self) -> EncodableBadge { serde_json::from_value(serde_json::to_value(self).unwrap()).unwrap() @@ -107,37 +93,4 @@ impl Badge { Ok(invalid_badges) }) } - - pub fn update_crate_old(conn: &GenericConnection, - krate: &Crate, - badges: HashMap>) - -> CargoResult> { - - let mut invalid_badges = vec![]; - - let badges: Vec = badges.into_iter().filter_map(|(k, v)| { - let json = json!({"badge_type": k, "attributes": v}); - serde_json::from_value(json) - .map_err(|_| invalid_badges.push(k)) - .ok() - }).collect(); - - conn.execute("\ - DELETE FROM badges \ - WHERE crate_id = $1;", - &[&krate.id] - )?; - - for badge in badges { - let json = serde_json::to_value(badge)?; - conn.execute("\ - INSERT INTO badges (crate_id, badge_type, attributes) \ - VALUES ($1, $2, $3) \ - ON CONFLICT (crate_id, badge_type) DO UPDATE \ - SET attributes = EXCLUDED.attributes;", - &[&krate.id, &json["badge_type"].as_str(), &json["attributes"]] - )?; - } - Ok(invalid_badges) - } } diff --git a/src/keyword.rs b/src/keyword.rs index c31a8eaf2ee..6c53d5877ad 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -1,5 +1,4 @@ use std::ascii::AsciiExt; -use std::collections::HashMap; use time::Timespec; use conduit::{Request, Response}; @@ -7,14 +6,12 @@ use conduit_router::RequestParams; use diesel::pg::PgConnection; use diesel::prelude::*; use diesel; -use pg::GenericConnection; use pg::rows::Row; use {Model, Crate}; use db::RequestTransaction; use schema::*; -use util::{RequestUtils, CargoResult, ChainError, internal}; -use util::errors::NotFound; +use util::{RequestUtils, CargoResult}; #[derive(Clone, Identifiable, Queryable)] pub struct Keyword { @@ -43,12 +40,11 @@ pub struct EncodableKeyword { } impl Keyword { - pub fn find_by_keyword(conn: &GenericConnection, name: &str) - -> CargoResult> { - let stmt = conn.prepare("SELECT * FROM keywords \ - WHERE keyword = LOWER($1)")?; - let rows = stmt.query(&[&name])?; - Ok(rows.iter().next().map(|r| Model::from_row(&r))) + pub fn find_by_keyword(conn: &PgConnection, name: &str) + -> QueryResult { + keywords::table + .filter(keywords::keyword.eq(::lower(name))) + .first(&*conn) } pub fn find_or_create_all(conn: &PgConnection, names: &[&str]) -> QueryResult> { @@ -60,58 +56,26 @@ impl Keyword { struct NewKeyword<'a> { keyword: &'a str, } - sql_function!(lower, lower_t, (x: ::diesel::types::Text) -> ::diesel::types::Text); - let (lowercase_names, new_keywords): (Vec<_>, Vec<_>) = names.iter() - .map(|s| (s.to_lowercase(), NewKeyword { keyword: *s })) - .unzip(); + let lowercase_names: Vec<_> = names.iter() + .map(|s| s.to_lowercase()) + .collect(); + + let new_keywords: Vec<_> = lowercase_names.iter() + .map(|s| NewKeyword { keyword: s }) + .collect(); // https://github.com/diesel-rs/diesel/issues/797 if !new_keywords.is_empty() { - diesel::insert(&new_keywords.on_conflict_do_nothing()).into(keywords::table) + diesel::insert(&new_keywords.on_conflict_do_nothing()) + .into(keywords::table) .execute(conn)?; } - keywords::table.filter(lower(keywords::keyword).eq(any(lowercase_names))) + keywords::table + .filter(::lower(keywords::keyword).eq(any(&lowercase_names))) .load(conn) } - pub fn find_or_insert(conn: &GenericConnection, name: &str) - -> CargoResult { - // TODO: racy (the select then insert is not atomic) - let stmt = conn.prepare("SELECT * FROM keywords - WHERE keyword = LOWER($1)")?; - for row in stmt.query(&[&name])?.iter() { - return Ok(Model::from_row(&row)) - } - - let stmt = conn.prepare("INSERT INTO keywords (keyword) VALUES (LOWER($1)) - RETURNING *")?; - let rows = stmt.query(&[&name])?; - Ok(Model::from_row(&rows.iter().next().chain_error(|| { - internal("no version returned") - })?)) - } - - pub fn all(conn: &GenericConnection, sort: &str, limit: i64, offset: i64) - -> CargoResult> { - - let sort_sql = match sort { - "crates" => "ORDER BY crates_cnt DESC", - _ => "ORDER BY keyword ASC", - }; - - let stmt = conn.prepare(&format!("SELECT * FROM keywords {} - LIMIT $1 OFFSET $2", - sort_sql))?; - - let keywords: Vec<_> = stmt.query(&[&limit, &offset])? - .iter() - .map(|row| Model::from_row(&row)) - .collect(); - - Ok(keywords) - } - pub fn valid_name(name: &str) -> bool { if name.is_empty() { return false } name.chars().next().unwrap().is_alphanumeric() && @@ -144,47 +108,6 @@ impl Keyword { Ok(()) }) } - - pub fn update_crate_old(conn: &GenericConnection, - krate: &Crate, - keywords: &[String]) -> CargoResult<()> { - let old_kws = krate.keywords(conn)?; - let old_kws = old_kws.iter().map(|kw| { - (&kw.keyword[..], kw) - }).collect::>(); - let new_kws = keywords.iter().map(|k| { - let kw = Keyword::find_or_insert(conn, k)?; - Ok((k.as_str(), kw)) - }).collect::>>()?; - - let to_rm = old_kws.iter().filter(|&(kw, _)| { - !new_kws.contains_key(kw) - }).map(|(_, v)| v.id).collect::>(); - let to_add = new_kws.iter().filter(|&(kw, _)| { - !old_kws.contains_key(kw) - }).map(|(_, v)| v.id).collect::>(); - - if !to_rm.is_empty() { - conn.execute("DELETE FROM crates_keywords - WHERE keyword_id = ANY($1) - AND crate_id = $2", - &[&to_rm, &krate.id])?; - } - - if !to_add.is_empty() { - let insert = to_add.iter().map(|id| { - let crate_id: i32 = krate.id; - let id: i32 = *id; - format!("({}, {})", crate_id, id) - }).collect::>().join(", "); - conn.execute(&format!("INSERT INTO crates_keywords - (crate_id, keyword_id) VALUES {}", - insert), - &[])?; - } - - Ok(()) - } } impl Model for Keyword { @@ -201,16 +124,31 @@ impl Model for Keyword { /// Handles the `GET /keywords` route. pub fn index(req: &mut Request) -> CargoResult { - let conn = req.tx()?; + use diesel::expression::dsl::sql; + use diesel::types::BigInt; + use schema::keywords; + + let conn = req.db_conn()?; let (offset, limit) = req.pagination(10, 100)?; let query = req.query(); let sort = query.get("sort").map(|s| &s[..]).unwrap_or("alpha"); - let keywords = Keyword::all(conn, sort, limit, offset)?; - let keywords = keywords.into_iter().map(Keyword::encodable).collect(); + let mut query = keywords::table + .select((keywords::all_columns, sql::("COUNT(*) OVER ()"))) + .limit(limit) + .offset(offset) + .into_boxed(); - // Query for the total count of keywords - let total = Keyword::count(conn)?; + if sort == "crates" { + query = query.order(keywords::crates_cnt.desc()); + } else { + query = query.order(keywords::keyword.asc()); + } + + let data = query.load::<(Keyword, i64)>(&*conn)?; + let total = data.get(0).map(|&(_, t)| t).unwrap_or(0); + let kws = data.into_iter() + .map(|(k, _)| k.encodable()).collect::>(); #[derive(RustcEncodable)] struct R { keywords: Vec, meta: Meta } @@ -218,7 +156,7 @@ pub fn index(req: &mut Request) -> CargoResult { struct Meta { total: i64 } Ok(req.json(&R { - keywords: keywords, + keywords: kws, meta: Meta { total: total }, })) } @@ -226,9 +164,9 @@ pub fn index(req: &mut Request) -> CargoResult { /// Handles the `GET /keywords/:keyword_id` route. pub fn show(req: &mut Request) -> CargoResult { let name = &req.params()["keyword_id"]; - let conn = req.tx()?; - let kw = Keyword::find_by_keyword(conn, name)?; - let kw = kw.chain_error(|| NotFound)?; + let conn = req.db_conn()?; + + let kw = Keyword::find_by_keyword(&conn, name)?; #[derive(RustcEncodable)] struct R { keyword: EncodableKeyword } diff --git a/src/krate.rs b/src/krate.rs index 850723d1c16..3c0993551e3 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -609,11 +609,8 @@ impl Crate { Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) } - pub fn badges(&self, conn: &GenericConnection) -> CargoResult> { - let stmt = conn.prepare("SELECT badges.* from badges \ - WHERE badges.crate_id = $1")?; - let rows = stmt.query(&[&self.id])?; - Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) + pub fn badges(&self, conn: &PgConnection) -> QueryResult> { + badges::table.filter(badges::crate_id.eq(self.id)).load(conn) } /// Returns (dependency, dependent crate name, dependent crate downloads) @@ -709,7 +706,7 @@ pub fn index(req: &mut Request) -> CargoResult { query = query.filter(crates::id.eq_any( crates_keywords::table.select(crates_keywords::crate_id) .inner_join(keywords::table) - .filter(lower(keywords::keyword).eq(lower(kw))) + .filter(::lower(keywords::keyword).eq(::lower(kw))) )); } else if let Some(letter) = params.get("letter") { let pattern = format!("{}%", letter.chars().next().unwrap() @@ -1303,4 +1300,3 @@ pub fn reverse_dependencies(req: &mut Request) -> CargoResult { use diesel::types::Text; sql_function!(canon_crate_name, canon_crate_name_t, (x: Text) -> Text); -sql_function!(lower, lower_t, (x: Text) -> Text); diff --git a/src/lib.rs b/src/lib.rs index 5b1d71743f8..25cf755e746 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -227,3 +227,5 @@ pub fn env(s: &str) -> String { panic!("must have `{}` defined", s) }) } + +sql_function!(lower, lower_t, (x: ::diesel::types::Text) -> ::diesel::types::Text); diff --git a/src/tests/all.rs b/src/tests/all.rs index 20c94f95662..382fb38ad60 100755 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -32,7 +32,7 @@ use cargo_registry::krate::NewCrate; use cargo_registry::upload as u; use cargo_registry::user::NewUser; use cargo_registry::version::NewVersion; -use cargo_registry::{User, Crate, Version, Keyword, Dependency, Category, Model, Replica}; +use cargo_registry::{User, Crate, Version, Dependency, Category, Model, Replica}; use conduit::{Request, Method}; use conduit_test::MockRequest; use diesel::pg::PgConnection; @@ -296,10 +296,6 @@ fn mock_dep(req: &mut Request, version: &Version, krate: &Crate, &target.map(|s| s.to_string())).unwrap() } -fn mock_keyword(req: &mut Request, name: &str) -> Keyword { - Keyword::find_or_insert(req.tx().unwrap(), name).unwrap() -} - fn new_category<'a>(category: &'a str, slug: &'a str) -> NewCategory<'a> { NewCategory { category: category, slug: slug, ..NewCategory::default() } } diff --git a/src/tests/badge.rs b/src/tests/badge.rs index 4425507f666..45da43dac23 100644 --- a/src/tests/badge.rs +++ b/src/tests/badge.rs @@ -1,11 +1,9 @@ -use conduit::Method; -use conduit_test::MockRequest; - +use cargo_registry::app::App; use cargo_registry::badge::Badge; -use cargo_registry::db::RequestTransaction; use cargo_registry::krate::Crate; use std::collections::HashMap; +use std::sync::Arc; struct BadgeRef { appveyor: Badge, @@ -16,12 +14,18 @@ struct BadgeRef { gitlab_attributes: HashMap, } -fn set_up() -> (MockRequest, Crate, BadgeRef) { +fn set_up() -> (Arc, Crate, BadgeRef) { let (_b, app, _middle) = ::app(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/badged_crate"); - ::mock_user(&mut req, ::user("foo")); - let (krate, _) = ::mock_crate(&mut req, ::krate("badged_crate")); + let krate = { + let conn = app.diesel_database.get().unwrap(); + let u = ::new_user("foo") + .create_or_update(&conn) + .unwrap(); + ::new_crate("badged_crate") + .create_or_update(&conn, None, u.id) + .unwrap() + }; let appveyor = Badge::Appveyor { service: Some(String::from("github")), @@ -74,67 +78,70 @@ fn set_up() -> (MockRequest, Crate, BadgeRef) { gitlab: gitlab, gitlab_attributes: badge_attributes_gitlab, }; - (req, krate, badges) + (app, krate, badges) } #[test] fn update_no_badges() { // Add no badges - let (req, krate, _) = set_up(); - - let badges = HashMap::new(); + let (app, krate, _) = set_up(); + let conn = app.diesel_database.get().unwrap(); // Updating with no badges has no effect - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![]); + Badge::update_crate(&conn, &krate, None).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![]); } #[test] fn update_add_appveyor() { // Add an appveyor badge - let (req, krate, test_badges) = set_up(); + let (app, krate, test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); badges.insert( String::from("appveyor"), test_badges.appveyor_attributes ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![test_badges.appveyor]); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); } #[test] fn update_add_travis_ci() { // Add a travis ci badge - let (req, krate, test_badges) = set_up(); + let (app, krate, test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); badges.insert( String::from("travis-ci"), test_badges.travis_ci_attributes ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![test_badges.travis_ci]); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); } #[test] fn update_add_gitlab() { // Add a gitlab badge - let (req, krate, test_badges) = set_up(); + let (app, krate, test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); badges.insert( String::from("gitlab"), test_badges.gitlab_attributes ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![test_badges.gitlab]); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); } #[test] fn replace_badge() { // Replacing one badge with another - let (req, krate, test_badges) = set_up(); + let (app, krate, test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); // Add a badge let mut badges = HashMap::new(); @@ -142,8 +149,8 @@ fn replace_badge() { String::from("gitlab"), test_badges.gitlab_attributes ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges.clone()).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![test_badges.gitlab]); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); // Replace with another badge badges.clear(); @@ -151,14 +158,15 @@ fn replace_badge() { String::from("travis-ci"), test_badges.travis_ci_attributes.clone() ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![test_badges.travis_ci]); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); } #[test] fn update_attributes() { // Update badge attributes - let (req, krate, test_badges) = set_up(); + let (app, krate, test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); // Add a travis-ci badge let mut badges = HashMap::new(); @@ -166,8 +174,8 @@ fn update_attributes() { String::from("travis-ci"), test_badges.travis_ci_attributes ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - let current_badges = krate.badges(req.tx().unwrap()).unwrap(); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 1); assert!(current_badges.contains(&test_badges.travis_ci)); @@ -186,8 +194,8 @@ fn update_attributes() { String::from("travis-ci"), badge_attributes_travis_ci2.clone() ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - let current_badges = krate.badges(req.tx().unwrap()).unwrap(); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 1); assert!(current_badges.contains(&travis_ci2)); } @@ -195,7 +203,8 @@ fn update_attributes() { #[test] fn clear_badges() { // Add 3 badges and then remove them - let (req, krate, test_badges) = set_up(); + let (app, krate, test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); @@ -212,9 +221,9 @@ fn clear_badges() { String::from("gitlab"), test_badges.gitlab_attributes ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges.clone()).unwrap(); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); - let current_badges = krate.badges(req.tx().unwrap()).unwrap(); + let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 3); assert!(current_badges.contains(&test_badges.appveyor)); assert!(current_badges.contains(&test_badges.travis_ci)); @@ -222,14 +231,15 @@ fn clear_badges() { // Removing all badges badges.clear(); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![]); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![]); } #[test] fn appveyor_extra_keys() { // Add a badge with extra invalid keys - let (req, krate, test_badges) = set_up(); + let (app, krate, test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); @@ -244,14 +254,15 @@ fn appveyor_extra_keys() { test_badges.appveyor_attributes ); - Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![test_badges.appveyor]); + Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); } #[test] fn travis_ci_required_keys() { // Add a travis ci badge missing a required field - let (req, krate, mut test_badges) = set_up(); + let (app, krate, mut test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); @@ -262,16 +273,17 @@ fn travis_ci_required_keys() { test_badges.travis_ci_attributes ); - let invalid_badges = Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); + let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); - assert!(invalid_badges.contains(&String::from("travis-ci"))); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![]); + assert!(invalid_badges.contains(&"travis-ci")); + assert_eq!(krate.badges(&conn).unwrap(), vec![]); } #[test] fn gitlab_required_keys() { // Add a gitlab badge missing a required field - let (req, krate, mut test_badges) = set_up(); + let (app, krate, mut test_badges) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); @@ -282,16 +294,17 @@ fn gitlab_required_keys() { test_badges.gitlab_attributes ); - let invalid_badges = Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); + let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); - assert!(invalid_badges.contains(&String::from("gitlab"))); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![]); + assert!(invalid_badges.contains(&"gitlab")); + assert_eq!(krate.badges(&conn).unwrap(), vec![]); } #[test] fn unknown_badge() { // Add an unknown badge - let (req, krate, _) = set_up(); + let (app, krate, _) = set_up(); + let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); @@ -306,8 +319,8 @@ fn unknown_badge() { invalid_attributes ); - let invalid_badges = Badge::update_crate_old(req.tx().unwrap(), &krate, badges).unwrap(); + let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); - assert!(invalid_badges.contains(&String::from("not-a-badge"))); - assert_eq!(krate.badges(req.tx().unwrap()).unwrap(), vec![]); + assert!(invalid_badges.contains(&"not-a-badge")); + assert_eq!(krate.badges(&conn).unwrap(), vec![]); } diff --git a/src/tests/keyword.rs b/src/tests/keyword.rs index 1c719172bc1..21edea2e92f 100644 --- a/src/tests/keyword.rs +++ b/src/tests/keyword.rs @@ -1,7 +1,6 @@ use conduit::{Handler, Method}; use conduit_test::MockRequest; -use cargo_registry::db::RequestTransaction; use cargo_registry::keyword::{Keyword, EncodableKeyword}; #[derive(RustcDecodable)] @@ -14,13 +13,16 @@ struct GoodKeyword { keyword: EncodableKeyword } #[test] fn index() { let (_b, app, middle) = ::app(); - let mut req = ::req(app, Method::Get, "/api/v1/keywords"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/keywords"); let mut response = ok_resp!(middle.call(&mut req)); let json: KeywordList = ::json(&mut response); assert_eq!(json.keywords.len(), 0); assert_eq!(json.meta.total, 0); - ::mock_keyword(&mut req, "foo"); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::find_or_create_all(&conn, &["foo"]).unwrap(); + } let mut response = ok_resp!(middle.call(&mut req)); let json: KeywordList = ::json(&mut response); assert_eq!(json.keywords.len(), 1); @@ -31,11 +33,14 @@ fn index() { #[test] fn show() { let (_b, app, middle) = ::app(); - let mut req = ::req(app, Method::Get, "/api/v1/keywords/foo"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/keywords/foo"); let response = t_resp!(middle.call(&mut req)); assert_eq!(response.status.0, 404); - ::mock_keyword(&mut req, "foo"); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::find_or_create_all(&conn, &["foo"]).unwrap(); + } let mut response = ok_resp!(middle.call(&mut req)); let json: GoodKeyword = ::json(&mut response); assert_eq!(json.keyword.keyword, "foo".to_string()); @@ -44,8 +49,11 @@ fn show() { #[test] fn uppercase() { let (_b, app, middle) = ::app(); - let mut req = ::req(app, Method::Get, "/api/v1/keywords/UPPER"); - ::mock_keyword(&mut req, "UPPER"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/keywords/UPPER"); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::find_or_create_all(&conn, &["UPPER"]).unwrap(); + } let mut res = ok_resp!(middle.call(&mut req)); let json: GoodKeyword = ::json(&mut res); @@ -55,40 +63,63 @@ fn uppercase() { #[test] fn update_crate() { let (_b, app, middle) = ::app(); - let mut req = ::req(app, Method::Get, "/api/v1/keywords/foo"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/keywords/foo"); let cnt = |req: &mut MockRequest, kw: &str| { req.with_path(&format!("/api/v1/keywords/{}", kw)); let mut response = ok_resp!(middle.call(req)); ::json::(&mut response).keyword.crates_cnt as usize }; - ::mock_user(&mut req, ::user("foo")); - let (krate, _) = ::mock_crate(&mut req, ::krate("fookey")); - ::mock_keyword(&mut req, "kw1"); - ::mock_keyword(&mut req, "kw2"); - Keyword::update_crate_old(req.tx().unwrap(), &krate, &[]).unwrap(); + let krate = { + let conn = app.diesel_database.get().unwrap(); + let u = ::new_user("foo") + .create_or_update(&conn) + .unwrap(); + Keyword::find_or_create_all(&conn, &["kw1", "kw2"]).unwrap(); + ::new_crate("fookey") + .create_or_update(&conn, None, u.id) + .unwrap() + }; + + { + let conn = app.diesel_database.get().unwrap(); + Keyword::update_crate(&conn, &krate, &[]).unwrap(); + } assert_eq!(cnt(&mut req, "kw1"), 0); assert_eq!(cnt(&mut req, "kw2"), 0); - Keyword::update_crate_old(req.tx().unwrap(), &krate, &["kw1".to_string()]).unwrap(); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::update_crate(&conn, &krate, &["kw1"]).unwrap(); + } assert_eq!(cnt(&mut req, "kw1"), 1); assert_eq!(cnt(&mut req, "kw2"), 0); - Keyword::update_crate_old(req.tx().unwrap(), &krate, &["kw2".to_string()]).unwrap(); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::update_crate(&conn, &krate, &["kw2"]).unwrap(); + } assert_eq!(cnt(&mut req, "kw1"), 0); assert_eq!(cnt(&mut req, "kw2"), 1); - Keyword::update_crate_old(req.tx().unwrap(), &krate, &[]).unwrap(); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::update_crate(&conn, &krate, &[]).unwrap(); + } assert_eq!(cnt(&mut req, "kw1"), 0); assert_eq!(cnt(&mut req, "kw2"), 0); - Keyword::update_crate_old(req.tx().unwrap(), &krate, &["kw1".to_string(), - "kw2".to_string()]).unwrap(); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::update_crate(&conn, &krate, &["kw1", "kw2"]).unwrap(); + } assert_eq!(cnt(&mut req, "kw1"), 1); assert_eq!(cnt(&mut req, "kw2"), 1); - Keyword::update_crate_old(req.tx().unwrap(), &krate, &[]).unwrap(); + { + let conn = app.diesel_database.get().unwrap(); + Keyword::update_crate(&conn, &krate, &[]).unwrap(); + } assert_eq!(cnt(&mut req, "kw1"), 0); assert_eq!(cnt(&mut req, "kw2"), 0); - }