use httpmock::{
Method::{GET, POST},
Mock, MockServer,
};
mod common;
use goose::config::GooseConfiguration;
use goose::goose::GooseTaskSet;
use goose::prelude::*;
const LOGIN_PATH: &str = "/login";
const LOGOUT_PATH: &str = "/logout";
const LOGIN_KEY: usize = 0;
const LOGOUT_KEY: usize = 1;
const EXPECT_WORKERS: usize = 2;
const USERS: usize = 5;
const RUN_TIME: usize = 2;
pub async fn login(user: &mut GooseUser) -> GooseTaskResult {
let params = [("username", "me"), ("password", "s3crET!")];
let _goose = user.post_form(LOGIN_PATH, ¶ms).await?;
Ok(())
}
pub async fn logout(user: &mut GooseUser) -> GooseTaskResult {
let _goose = user.get(LOGOUT_PATH).await?;
Ok(())
}
fn setup_mock_server_endpoints(server: &MockServer) -> Vec<Mock> {
vec![
server.mock(|when, then| {
when.method(POST).path(LOGIN_PATH);
then.status(200);
}),
server.mock(|when, then| {
when.method(GET).path(LOGOUT_PATH);
then.status(200);
}),
]
}
fn common_build_configuration(
server: &MockServer,
worker: Option<bool>,
manager: Option<usize>,
) -> GooseConfiguration {
if let Some(expect_workers) = manager {
common::build_configuration(
server,
vec![
"--manager",
"--expect-workers",
&expect_workers.to_string(),
"--users",
&USERS.to_string(),
"--hatch-rate",
&USERS.to_string(),
"--run-time",
&RUN_TIME.to_string(),
"--no-reset-metrics",
],
)
} else if worker.is_some() {
common::build_configuration(server, vec!["--worker"])
} else {
common::build_configuration(
server,
vec![
"--users",
&USERS.to_string(),
"--hatch-rate",
&USERS.to_string(),
"--run-time",
&RUN_TIME.to_string(),
"--no-reset-metrics",
],
)
}
}
fn validate_test(mock_endpoints: &[Mock]) {
mock_endpoints[LOGIN_KEY].assert_hits(USERS);
mock_endpoints[LOGOUT_KEY].assert_hits(USERS);
}
fn get_tasks() -> GooseTaskSet {
taskset!("LoadTest")
.register_task(task!(login).set_on_start())
.register_task(task!(logout).set_on_stop())
}
async fn run_load_test(is_gaggle: bool) {
let server = MockServer::start();
let mock_endpoints = setup_mock_server_endpoints(&server);
match is_gaggle {
false => {
let configuration = common_build_configuration(&server, None, None);
common::run_load_test(
common::build_load_test(configuration, &get_tasks(), None, None),
None,
)
.await;
}
true => {
let worker_configuration = common_build_configuration(&server, Some(true), None);
let worker_handles = common::launch_gaggle_workers(EXPECT_WORKERS, || {
common::build_load_test(worker_configuration.clone(), &get_tasks(), None, None)
});
let manager_configuration =
common_build_configuration(&server, None, Some(EXPECT_WORKERS));
common::run_load_test(
common::build_load_test(manager_configuration, &get_tasks(), None, None),
Some(worker_handles),
)
.await;
}
}
validate_test(&mock_endpoints);
}
#[tokio::test]
async fn test_no_normal_tasks() {
run_load_test(false).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 8)]
#[cfg_attr(not(feature = "gaggle"), ignore)]
async fn test_no_normal_tasks_gaggle() {
run_load_test(true).await;
}