use goose::prelude::*;
use rand::Rng;
use regex::Regex;
fn main() {
GooseAttack::initialize()
.register_taskset(
taskset!("AnonBrowsingUser")
.set_weight(4)
.register_task(
task!(drupal_loadtest_front_page)
.set_weight(15)
.set_name("(Anon) front page"),
)
.register_task(
task!(drupal_loadtest_node_page)
.set_weight(10)
.set_name("(Anon) node page"),
)
.register_task(
task!(drupal_loadtest_profile_page)
.set_weight(3)
.set_name("(Anon) user page"),
),
)
.register_taskset(
taskset!("AuthBrowsingUser")
.set_weight(1)
.register_task(
task!(drupal_loadtest_login)
.set_on_start()
.set_name("(Auth) login"),
)
.register_task(
task!(drupal_loadtest_front_page)
.set_weight(15)
.set_name("(Auth) front page"),
)
.register_task(
task!(drupal_loadtest_node_page)
.set_weight(10)
.set_name("(Auth) node page"),
)
.register_task(
task!(drupal_loadtest_profile_page)
.set_weight(3)
.set_name("(Auth) user page"),
)
.register_task(
task!(drupal_loadtest_post_comment)
.set_weight(3)
.set_name("(Auth) comment form"),
),
)
.execute();
}
async fn drupal_loadtest_front_page(client: &GooseClient) {
let mut response = client.get("/").await;
match response.response {
Ok(r) => match r.text().await {
Ok(t) => {
let re = Regex::new(r#"src="(.*?)""#).unwrap();
let mut urls = Vec::new();
for url in re.captures_iter(&t) {
if url[1].contains("/misc") || url[1].contains("/themes") {
urls.push(url[1].to_string());
}
}
for index in 0..urls.len() {
client.get_named(&urls[index], "static asset").await;
}
}
Err(e) => {
eprintln!("failed to parse front page: {}", e);
client.set_failure(&mut response.request);
}
},
Err(e) => {
eprintln!("unexpected error when loading front page: {}", e);
client.set_failure(&mut response.request);
}
}
}
async fn drupal_loadtest_node_page(client: &GooseClient) {
let nid = rand::thread_rng().gen_range(1, 10_000);
let _response = client.get(format!("/node/{}", &nid).as_str()).await;
}
async fn drupal_loadtest_profile_page(client: &GooseClient) {
let uid = rand::thread_rng().gen_range(2, 5_001);
let _response = client.get(format!("/user/{}", &uid).as_str()).await;
}
async fn drupal_loadtest_login(client: &GooseClient) {
let mut response = client.get("/user").await;
match response.response {
Ok(r) => {
match r.text().await {
Ok(html) => {
let re = Regex::new(r#"name="form_build_id" value=['"](.*?)['"]"#).unwrap();
let form_build_id = match re.captures(&html) {
Some(f) => f,
None => {
eprintln!("no form_build_id on page: /user page");
client.set_failure(&mut response.request);
return;
}
};
let uid = rand::thread_rng().gen_range(3, 5_002);
let username = format!("user{}", uid);
let params = [
("name", username.as_str()),
("pass", "12345"),
("form_build_id", &form_build_id[1]),
("form_id", "user_login"),
("op", "Log+in"),
];
let request_builder = client.goose_post("/user").await;
let _response = client.goose_send(request_builder.form(¶ms), None).await;
}
Err(e) => {
eprintln!("unexpected error when loading /user page: {}", e);
client.set_failure(&mut response.request);
}
}
}
Err(_) => (),
}
}
async fn drupal_loadtest_post_comment(client: &GooseClient) {
let nid: i32 = rand::thread_rng().gen_range(1, 10_000);
let node_path = format!("node/{}", &nid);
let comment_path = format!("/comment/reply/{}", &nid);
let mut response = client.get(&node_path).await;
match response.response {
Ok(r) => {
match r.text().await {
Ok(html) => {
let re = Regex::new(r#"name="form_build_id" value=['"](.*?)['"]"#).unwrap();
let form_build_id = match re.captures(&html) {
Some(f) => f,
None => {
eprintln!("no form_build_id found on {}", &node_path);
client.set_failure(&mut response.request);
return;
}
};
let re = Regex::new(r#"name="form_token" value=['"](.*?)['"]"#).unwrap();
let form_token = match re.captures(&html) {
Some(f) => f,
None => {
eprintln!("no form_token found on {}", &node_path);
client.set_failure(&mut response.request);
return;
}
};
let re = Regex::new(r#"name="form_id" value=['"](.*?)['"]"#).unwrap();
let form_id = match re.captures(&html) {
Some(f) => f,
None => {
eprintln!("no form_id found on {}", &node_path);
client.set_failure(&mut response.request);
return;
}
};
let comment_body = "this is a test comment body";
let params = [
("subject", "this is a test comment subject"),
("comment_body[und][0][value]", &comment_body),
("comment_body[und][0][format]", "filtered_html"),
("form_build_id", &form_build_id[1]),
("form_token", &form_token[1]),
("form_id", &form_id[1]),
("op", "Save"),
];
let request_builder = client.goose_post(&comment_path).await;
let mut response = client.goose_send(request_builder.form(¶ms), None).await;
match response.response {
Ok(r) => match r.text().await {
Ok(html) => {
if !html.contains(&comment_body) {
eprintln!(
"no comment showed up after posting to {}",
&comment_path
);
client.set_failure(&mut response.request);
}
}
Err(e) => {
eprintln!(
"unexpected error when posting to {}: {}",
&comment_path, e
);
client.set_failure(&mut response.request);
}
},
Err(_) => (),
}
}
Err(e) => {
eprintln!("unexpected error when loading {} page: {}", &node_path, e);
client.set_failure(&mut response.request);
}
}
}
Err(_) => (),
}
}