campaign workflow tests

This commit is contained in:
Aravinth Manivannan 2021-10-11 19:17:28 +05:30
parent 2c4d2e5358
commit 377b825fe4
Signed by: realaravinth
GPG key ID: AD9F0F08E855ED88
4 changed files with 284 additions and 84 deletions

View file

@ -87,22 +87,6 @@
"nullable": [] "nullable": []
} }
}, },
"3e31af624e06a2261fa85f25b5ec4c62a8408cd7283042e24b2aee2998931426": {
"query": "\nINSERT INTO survey_campaigns (\n user_id, ID, name, difficulties, created_at\n ) VALUES(\n (SELECT id FROM survey_admins WHERE name = $1),\n $2, $3, $4, $5\n );",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Uuid",
"Varchar",
"Int4Array",
"Timestamptz"
]
},
"nullable": []
}
},
"43b3e771f38bf8059832169227705be06a28925af1b3799ffef5371d511fd138": { "43b3e771f38bf8059832169227705be06a28925af1b3799ffef5371d511fd138": {
"query": "\n INSERT INTO survey_users (created_at, id) VALUES($1, $2)", "query": "\n INSERT INTO survey_users (created_at, id) VALUES($1, $2)",
"describe": { "describe": {
@ -182,6 +166,22 @@
] ]
} }
}, },
"82feafc36533144e49ba374c8c47ca4aa0d6558a9803778ad28cfa7b62382c3e": {
"query": "\n INSERT INTO survey_campaigns (\n user_id, ID, name, difficulties, created_at\n ) VALUES(\n (SELECT id FROM survey_admins WHERE name = $1),\n $2, $3, $4, $5\n );",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Uuid",
"Varchar",
"Int4Array",
"Timestamptz"
]
},
"nullable": []
}
},
"8320dda2b3e107d1451fdfb35eb2a4b8e97364e7b1b74ffe4d6913faf132fb61": { "8320dda2b3e107d1451fdfb35eb2a4b8e97364e7b1b74ffe4d6913faf132fb61": {
"query": "SELECT ID \n FROM survey_responses \n WHERE \n user_id = $1 \n AND \n device_software_recognised = $2;", "query": "SELECT ID \n FROM survey_responses \n WHERE \n user_id = $1 \n AND \n device_software_recognised = $2;",
"describe": { "describe": {

View file

@ -45,18 +45,20 @@ pub mod runners {
pub async fn add_runner( pub async fn add_runner(
username: &str, username: &str,
payload: &AddCapmaign, payload: &mut AddCapmaign,
data: &AppData, data: &AppData,
) -> ServiceResult<uuid::Uuid> { ) -> ServiceResult<uuid::Uuid> {
let mut uuid; let mut uuid;
let now = OffsetDateTime::now_utc(); let now = OffsetDateTime::now_utc();
payload.difficulties.sort();
loop { loop {
uuid = get_uuid(); uuid = get_uuid();
let res = sqlx::query!( let res = sqlx::query!(
" "
INSERT INTO survey_campaigns ( INSERT INTO survey_campaigns (
user_id, ID, name, difficulties, created_at user_id, ID, name, difficulties, created_at
) VALUES( ) VALUES(
(SELECT id FROM survey_admins WHERE name = $1), (SELECT id FROM survey_admins WHERE name = $1),
@ -89,13 +91,19 @@ INSERT INTO survey_campaigns (
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct AddCapmaign { pub struct AddCapmaign {
name: String, pub name: String,
difficulties: Vec<i32>, pub difficulties: Vec<i32>,
}
#[derive(Serialize, Deserialize)]
pub struct AddCapmaignResp {
pub campaign_id: String,
} }
pub fn services(cfg: &mut web::ServiceConfig) { pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(add); cfg.service(add);
} }
#[my_codegen::post(path = "crate::V1_API_ROUTES.admin.campaign.add")] #[my_codegen::post(path = "crate::V1_API_ROUTES.admin.campaign.add")]
async fn add( async fn add(
payload: web::Json<AddCapmaign>, payload: web::Json<AddCapmaign>,
@ -103,7 +111,82 @@ async fn add(
id: Identity, id: Identity,
) -> ServiceResult<impl Responder> { ) -> ServiceResult<impl Responder> {
let username = id.identity().unwrap(); let username = id.identity().unwrap();
let payload = payload.into_inner(); let mut payload = payload.into_inner();
let _campaign_id = runners::add_runner(&username, &payload, &data).await?; let campaign_id = runners::add_runner(&username, &mut payload, &data).await?;
Ok(HttpResponse::Ok()) let resp = AddCapmaignResp {
campaign_id: campaign_id.to_string(),
};
Ok(HttpResponse::Ok().json(resp))
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use crate::api::v1::bench::{Bench, BenchConfig, Submission, SubmissionProof};
use crate::data::Data;
use crate::tests::*;
use crate::*;
#[actix_rt::test]
async fn test_add_campaign() {
const NAME: &str = "testadminuser";
const EMAIL: &str = "testuserupda@testadminuser.com";
const PASSWORD: &str = "longpassword2";
const DEVICE_USER_PROVIDED: &str = "foo";
const DEVICE_SOFTWARE_RECOGNISED: &str = "Foobar.v2";
const THREADS: i32 = 4;
let benches = vec![
Bench {
difficulty: 1,
duration: 1.00,
},
Bench {
difficulty: 2,
duration: 2.00,
},
Bench {
difficulty: 3,
duration: 3.00,
},
Bench {
difficulty: 4,
duration: 4.00,
},
Bench {
difficulty: 5,
duration: 5.00,
},
];
{
let data = Data::new().await;
delete_user(NAME, &data).await;
}
let (data, _creds, signin_resp) =
register_and_signin(NAME, EMAIL, PASSWORD).await;
let cookies = get_cookie!(signin_resp);
let survey = get_survey_user(data.clone()).await;
let survey_cookie = get_cookie!(survey);
// let app = get_app!(data).await;
let campaign = create_new_campaign(NAME, data.clone(), cookies.clone()).await;
let campaign_config =
get_campaign_config(&campaign, data.clone(), survey_cookie.clone()).await;
assert_eq!(DIFFICULTIES.to_vec(), campaign_config.difficulties);
let submit_payload = Submission {
device_user_provided: DEVICE_USER_PROVIDED.into(),
device_software_recognised: DEVICE_SOFTWARE_RECOGNISED.into(),
threads: THREADS,
benches: benches.clone(),
};
let _proof =
submit_bench(&submit_payload, &campaign, survey_cookie, data.clone()).await;
}
} }

View file

@ -99,31 +99,31 @@ pub mod runners {
} }
} }
#[my_codegen::post(path = "crate::V1_API_ROUTES.benches.register")] #[my_codegen::get(path = "crate::V1_API_ROUTES.benches.register")]
async fn register(data: AppData, id: Identity) -> ServiceResult<impl Responder> { async fn register(data: AppData, id: Identity) -> ServiceResult<impl Responder> {
let uuid = runners::register_runner(&data).await?; let uuid = runners::register_runner(&data).await?;
id.remember(uuid.to_string()); id.remember(uuid.to_string());
Ok(HttpResponse::Ok()) Ok(HttpResponse::Ok())
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Clone)]
struct Bench { pub struct Bench {
duration: f32, pub duration: f32,
difficulty: i32, pub difficulty: i32,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Clone)]
struct Submission { pub struct Submission {
device_user_provided: String, pub device_user_provided: String,
device_software_recognised: String, pub device_software_recognised: String,
threads: i32, pub threads: i32,
benches: Vec<Bench>, pub benches: Vec<Bench>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Clone)]
struct SubmissionProof { pub struct SubmissionProof {
token: String, pub token: String,
proof: String, pub proof: String,
} }
fn get_check_login() -> crate::CheckLogin { fn get_check_login() -> crate::CheckLogin {

View file

@ -14,15 +14,21 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use actix_web::cookie::Cookie; use actix_web::cookie::Cookie;
use actix_web::test; use actix_web::test;
use actix_web::{dev::ServiceResponse, error::ResponseError, http::StatusCode}; use actix_web::{dev::ServiceResponse, error::ResponseError, http::StatusCode};
use serde::Serialize; use serde::Serialize;
use uuid::Uuid;
use super::*; use super::*;
use crate::api::v1::admin::auth::runners::{Login, Register}; use crate::api::v1::admin::{
auth::runners::{Login, Register},
campaigns::{AddCapmaign, AddCapmaignResp},
};
use crate::api::v1::bench::{Bench, BenchConfig, Submission, SubmissionProof};
use crate::data::Data; use crate::data::Data;
use crate::errors::*; use crate::errors::*;
use crate::V1_API_ROUTES; use crate::V1_API_ROUTES;
@ -91,7 +97,7 @@ macro_rules! get_app {
test::init_service(get_app!("APP")) test::init_service(get_app!("APP"))
}; };
($data:expr) => { ($data:expr) => {
test::init_service( actix_web::test::init_service(
get_app!("APP").app_data(actix_web::web::Data::new($data.clone())), get_app!("APP").app_data(actix_web::web::Data::new($data.clone())),
) )
}; };
@ -192,29 +198,62 @@ pub async fn bad_post_req_test<T: Serialize>(
// //println!("{}", txt.error); // //println!("{}", txt.error);
// assert_eq!(resp_err.error, format!("{}", err)); // assert_eq!(resp_err.error, format!("{}", err));
//} //}
//
//pub async fn create_new_campaign( pub const DIFFICULTIES: [i32; 5] = [1, 2, 3, 4, 5];
// campaign_name: &str,
// data: Arc<Data>, pub async fn create_new_campaign(
// cookies: Cookie<'_>, campaign_name: &str,
//) -> CreateResp { data: Arc<Data>,
// let new = CreateReq { cookies: Cookie<'_>,
// name: campaign_name.into(), ) -> AddCapmaignResp {
// }; let new = AddCapmaign {
// name: campaign_name.into(),
// let app = get_app!(data).await; difficulties: DIFFICULTIES.into(),
// let new_resp = test::call_service( };
// &app,
// post_request!(&new, crate::V1_API_ROUTES.campaign.new) let app = get_app!(data).await;
// .cookie(cookies) let new_resp = test::call_service(
// .to_request(), &app,
// ) post_request!(&new, crate::V1_API_ROUTES.admin.campaign.add)
// .await; .cookie(cookies)
// assert_eq!(new_resp.status(), StatusCode::OK); .to_request(),
// let uuid: CreateResp = test::read_body_json(new_resp).await; )
// uuid .await;
//} assert_eq!(new_resp.status(), StatusCode::OK);
// let uuid: AddCapmaignResp = test::read_body_json(new_resp).await;
uuid
}
pub async fn get_survey_user(data: Arc<Data>) -> ServiceResponse {
let app = get_app!(data).await;
let signin_resp = test::call_service(
&app,
test::TestRequest::get()
.uri(V1_API_ROUTES.benches.register)
.to_request(),
)
.await;
assert_eq!(signin_resp.status(), StatusCode::OK);
signin_resp
}
pub async fn get_campaign_config(
campaign: &AddCapmaignResp,
data: Arc<Data>,
cookies: Cookie<'_>,
) -> BenchConfig {
let app = get_app!(data).await;
let route = V1_API_ROUTES
.benches
.fetch_routes(&campaign.campaign_id.to_string());
let new_resp =
test::call_service(&app, post_request!(&route).cookie(cookies).to_request())
.await;
assert_eq!(new_resp.status(), StatusCode::OK);
test::read_body_json(new_resp).await
}
//pub async fn delete_campaign( //pub async fn delete_campaign(
// camapign: &CreateResp, // camapign: &CreateResp,
// data: Arc<Data>, // data: Arc<Data>,
@ -244,22 +283,100 @@ pub async fn bad_post_req_test<T: Serialize>(
// test::read_body_json(list_resp).await // test::read_body_json(list_resp).await
//} //}
// //
//pub async fn add_feedback( pub async fn submit_bench(
// rating: &RatingReq, payload: &Submission,
// campaign: &CreateResp, campaign: &AddCapmaignResp,
// data: Arc<Data>, cookies: Cookie<'_>,
//) -> RatingResp { data: Arc<Data>,
// let add_feedback_route = V1_API_ROUTES.feedback.add_feedback_route(&campaign.uuid); ) -> SubmissionProof {
// let app = get_app!(data).await; let route = V1_API_ROUTES.benches.submit_route(&campaign.campaign_id);
// let add_feedback_resp = test::call_service( let app = get_app!(data).await;
// &app, let add_feedback_resp = test::call_service(
// post_request!(&rating, &add_feedback_route).to_request(), &app,
// ) post_request!(&payload, &route).cookie(cookies).to_request(),
// .await; )
// assert_eq!(add_feedback_resp.status(), StatusCode::OK); .await;
// assert_eq!(add_feedback_resp.status(), StatusCode::OK);
// test::read_body_json(add_feedback_resp).await
//} let proof: SubmissionProof = test::read_body_json(add_feedback_resp).await;
let survey_user_id = Uuid::from_str(&proof.token).unwrap();
let proof_uuid = Uuid::from_str(&proof.proof).unwrap();
struct Exists {
exists: Option<bool>,
}
let res = sqlx::query_as!(
Exists,
"SELECT EXISTS (
SELECT 1 from survey_responses
WHERE device_software_recognised = $1
AND device_user_provided = $2
AND THREADS = $3
AND user_id = $4
);",
&payload.device_software_recognised,
&payload.device_user_provided,
payload.threads,
&survey_user_id,
)
.fetch_one(&data.db)
.await
.unwrap();
assert!(res.exists.as_ref().unwrap());
let res = sqlx::query_as!(
Exists,
"SELECT EXISTS (
SELECT 1 from survey_response_tokens
WHERE id = $1
);",
&proof_uuid
)
.fetch_one(&data.db)
.await
.unwrap();
assert!(res.exists.as_ref().unwrap());
struct ID {
id: i32,
}
let resp_id = sqlx::query_as!(
ID,
"SELECT ID
FROM survey_responses
WHERE
user_id = $1
AND
device_software_recognised = $2;",
&survey_user_id,
&payload.device_software_recognised
)
.fetch_one(&data.db)
.await
.unwrap();
for bench in payload.benches.iter() {
let res = sqlx::query_as!(
Exists,
"SELECT EXISTS(
SELECT 1 FROM survey_benches
WHERE resp_id = $1
AND difficulty = $2
AND duration = $3);",
&resp_id.id,
&bench.difficulty,
bench.duration
)
.fetch_one(&data.db)
.await
.unwrap();
assert!(res.exists.as_ref().unwrap());
}
proof
}
// //
//pub async fn get_feedback( //pub async fn get_feedback(
// campaign: &CreateResp, // campaign: &CreateResp,