mirror of
https://gitlab.com/keys.openpgp.org/hagrid.git
synced 2025-10-06 00:23:08 +02:00
Refactor helper functions in tests of hagrid::web module into fixtures.
Fixtures allow for push-style cascading dependency resolution with ability to override some of the dependent fixture's arguments when needed. This is very nice as it gives a lot of flexibility and suitable in a lot of case. So, single fixture based approach can be applied to most of the tests. In addition, this result in good reusability of test code. If you feel overwelmed and confused with complex argument list of test functions try to read links from "Documentation" section (see below). But here is the primer. #[fixture] pub fn configuration( base_uri: &str, base_uri_onion: &str, ) -> (TempDir, :🚀:figment::Figment) { // ... } Attribute #[fixture] turn function into fixture which means now it can be injected into tests or other fixtures by "configuration" argument name. "base_uri", "base_uri_onion" are other fixtures which are injected into "configuration". #[fixture] pub fn rocket( #[from(configuration)] (tmpdir, config): (TempDir, :🚀:figment::Figment), ) -> (TempDir, :🚀:Rocket<:🚀:Build>) { // ... } As we destructuring results of "configuration" fixture injection into "rocket" fixture the name of the fixture can't be inferenced from parameters name, so we have to give a hint with #[from(configuration)] which fixture has to be called. #[rstest] fn hkp_add_two( base_uri: &str, #[from(cert)] (_, tpk_0): (&str, Cert), #[with(alt_cert_name())] #[from(cert)] (_, tpk_1): (&str, Cert), #[from(client)] (tmpdir, client): (TempDir, Client), ) { // ... } This is probably the most trickies function signature, but let brake it down. There are 4 fixtures injected into "hkp_add_two" test function: - base_uri - cert - cert - client I think at this point of explanation syntax for "base_uri" and "client" fixturex should be clear. So, #[from(cert)] (_, tpk_0): (&str, Cert), #[with(alt_cert_name())] #[from(cert)] (_, tpk_1): (&str, Cert), calls to "cert" fixture which takes "cert_name" argument. Here is the definition: #[fixture] pub fn cert<'a>(cert_name: &'a str) -> (&'a str, Cert) { // ... } For the "hkp_add_two" test we need two certificates, so first one is generated with default name which is returned by "cert_name" fixture, but for the second with #[with(alt_cert_name())] we say that we want to use "alt_cert_name" fixture for cert_name argument, so the certificate is generated with "bar@invalid.example.com" name. And parenthis for destructing of the results of injection as "cert" fixture returns tuple of (cert_name, cert). Documentation: - https://crates.io/crates/rstest - https://docs.rs/rstest/0.26.1/rstest/attr.fixture.html NOTE: probably this changes made translation generation in tests more unstable. It was already unstable, but it looks like the use of fixtures make a bit more unstable. So, in case of test failures, just run them several times. I'll take a look and modules compilation order later once move tests into modules with SUT's functionality. Changes: - Turn the following helper functions from hagrid::web::tests module to fixtures: - configuration() - rocket() - client() - Panic immediately in the fixtures and don't bubble up the error like it was in helper functions. Bubbling up errors does not make sense as we panic with expect later in tests code. So, we duplicated code (.unwrap()) calls) and make return signatures more complex. - Inject "base_uri" and "base_uri_onion" into "configuration" fixture as after turning it into fixture we can do that. - Remove BASE_URI_ONION constant as it is not used. Now "base_uri_onion" fixture is used instead. - Refactor all the tests which used mentioned above helper functions to use fixture.
This commit is contained in:
committed by
Vincent Breitmoser
parent
0d868ce27e
commit
76ec3eed82
@@ -182,21 +182,25 @@ pub fn key_to_hkp_index(db: &rocket::State<Sqlite>, i18n: I18n, query: Query) ->
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::tests::common::*;
|
||||
use super::super::tests::*;
|
||||
use ::rocket::local::blocking::Client;
|
||||
use rstest::rstest;
|
||||
|
||||
use rocket::http::ContentType;
|
||||
use rocket::http::Status;
|
||||
|
||||
use sequoia_openpgp::Cert;
|
||||
use sequoia_openpgp::serialize::Serialize;
|
||||
use ::rocket::http::ContentType;
|
||||
use ::rocket::http::Status;
|
||||
|
||||
use crate::mail::pop_mail;
|
||||
use crate::web::tests::*;
|
||||
use crate::web::tests::common::*;
|
||||
use sequoia_openpgp::Cert;
|
||||
use sequoia_openpgp::serialize::Serialize;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[rstest]
|
||||
fn hkp(base_uri: &str, #[from(cert)] (cert_name, tpk): (&str, Cert)) {
|
||||
let (tmpdir, client) = client().unwrap();
|
||||
fn hkp(
|
||||
base_uri: &str,
|
||||
#[from(cert)] (cert_name, tpk): (&str, Cert),
|
||||
#[from(client)] (tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let filemail_into = tmpdir.path().join("filemail");
|
||||
|
||||
// eprintln!("LEAKING: {:?}", tmpdir);
|
||||
@@ -270,12 +274,12 @@ mod tests {
|
||||
#[rstest]
|
||||
fn hkp_add_two(
|
||||
base_uri: &str,
|
||||
#[from(cert)] (cert_name_0, tpk_0): (&str, Cert),
|
||||
#[from(cert)] (_, tpk_0): (&str, Cert),
|
||||
#[with(alt_cert_name())]
|
||||
#[from(cert)]
|
||||
(cert_name_1, tpk_1): (&str, Cert),
|
||||
(_, tpk_1): (&str, Cert),
|
||||
#[from(client)] (tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let (tmpdir, client) = client().unwrap();
|
||||
let filemail_into = tmpdir.path().join("filemail");
|
||||
|
||||
// Prepare to /pks/add
|
||||
|
242
src/web/mod.rs
242
src/web/mod.rs
@@ -296,35 +296,36 @@ pub fn key_to_response_plain(db: &rocket::State<Sqlite>, i18n: I18n, query: Quer
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use ::rocket::http::ContentType;
|
||||
use ::rocket::http::Header;
|
||||
use ::rocket::http::Status;
|
||||
use ::rocket::local::blocking::{Client, LocalResponse};
|
||||
use regex;
|
||||
use rocket::http::ContentType;
|
||||
use rocket::http::Header;
|
||||
use rocket::http::Status;
|
||||
use rocket::local::blocking::{Client, LocalResponse};
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tempfile::{TempDir, tempdir};
|
||||
use std::path::Path;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use sequoia_openpgp::Cert;
|
||||
use sequoia_openpgp::cert::CertBuilder;
|
||||
use sequoia_openpgp::parse::Parse;
|
||||
use sequoia_openpgp::serialize::Serialize;
|
||||
|
||||
use super::*;
|
||||
use crate::app::configure_rocket;
|
||||
use crate::mail::pop_mail;
|
||||
use crate::web::tests::common::{base_uri, base_uri_onion};
|
||||
use rstest::rstest;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use common::*;
|
||||
|
||||
pub mod common {
|
||||
use crate::app::configure_rocket;
|
||||
use ::rocket::local::blocking::Client;
|
||||
use rstest::fixture;
|
||||
use sequoia_openpgp::Cert;
|
||||
use sequoia_openpgp::cert::CertBuilder;
|
||||
use std::path::PathBuf;
|
||||
use tempfile::{TempDir, tempdir};
|
||||
|
||||
/// Fake base URI to use in tests.
|
||||
#[fixture]
|
||||
@@ -358,100 +359,107 @@ pub mod tests {
|
||||
|
||||
(cert_name, tpk)
|
||||
}
|
||||
|
||||
/// Creates a configuration and empty state dir for testing purposes.
|
||||
///
|
||||
/// Note that you need to keep the returned TempDir alive for the
|
||||
/// duration of your test. To debug the test, mem::forget it to
|
||||
/// prevent cleanup.
|
||||
#[fixture]
|
||||
pub fn configuration(
|
||||
base_uri: &str,
|
||||
base_uri_onion: &str,
|
||||
) -> (TempDir, ::rocket::figment::Figment) {
|
||||
let root = tempdir().expect("valid temporary directory for configuration");
|
||||
|
||||
let filemail = root.path().join("filemail");
|
||||
::std::fs::create_dir_all(&filemail).expect("valid temporary directory for filemail");
|
||||
|
||||
let base_dir: PathBuf = root.path().into();
|
||||
|
||||
let config = ::rocket::Config::figment()
|
||||
.select("staging")
|
||||
.merge(("root", root.path()))
|
||||
.merge((
|
||||
"template_dir",
|
||||
::std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("dist/templates")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"email_template_dir",
|
||||
::std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("dist/email-templates")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"assets_dir",
|
||||
::std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("dist/assets")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"keys_internal_dir",
|
||||
base_dir.join("keys_internal").to_str().unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"keys_external_dir",
|
||||
base_dir.join("keys_external").to_str().unwrap(),
|
||||
))
|
||||
.merge(("tmp_dir", base_dir.join("tmp").to_str().unwrap()))
|
||||
.merge(("token_dir", base_dir.join("tokens").to_str().unwrap()))
|
||||
.merge((
|
||||
"maintenance_file",
|
||||
base_dir.join("maintenance").to_str().unwrap(),
|
||||
))
|
||||
.merge(("base-URI", base_uri))
|
||||
.merge(("base-URI-Onion", base_uri_onion))
|
||||
.merge(("from", "from@example.com"))
|
||||
.merge(("token_secret", "hagrid"))
|
||||
.merge(("token_validity", 3600u64))
|
||||
.merge((
|
||||
"filemail_into",
|
||||
filemail
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("path is valid UTF8"),
|
||||
));
|
||||
|
||||
(root, config)
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
pub fn rocket(
|
||||
#[from(configuration)] (tmpdir, config): (TempDir, ::rocket::figment::Figment),
|
||||
) -> (TempDir, ::rocket::Rocket<::rocket::Build>) {
|
||||
(tmpdir, configure_rocket(::rocket::custom(config)))
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
pub fn client(
|
||||
#[from(rocket)] (tmpdir, rocket): (TempDir, ::rocket::Rocket<::rocket::Build>),
|
||||
) -> (TempDir, Client) {
|
||||
let client = Client::untracked(rocket).expect("valid rocket instance");
|
||||
|
||||
(tmpdir, client)
|
||||
}
|
||||
}
|
||||
|
||||
const BASE_URI: &str = "http://local.connection";
|
||||
const BASE_URI_ONION: &str = "http://local.connection.onion";
|
||||
|
||||
/// Creates a configuration and empty state dir for testing purposes.
|
||||
///
|
||||
/// Note that you need to keep the returned TempDir alive for the
|
||||
/// duration of your test. To debug the test, mem::forget it to
|
||||
/// prevent cleanup.
|
||||
pub fn configuration() -> anyhow::Result<(TempDir, rocket::figment::Figment)> {
|
||||
let root = tempdir()?;
|
||||
let filemail = root.path().join("filemail");
|
||||
::std::fs::create_dir_all(&filemail)?;
|
||||
|
||||
let base_dir: PathBuf = root.path().into();
|
||||
|
||||
let config = rocket::Config::figment()
|
||||
.select("staging")
|
||||
.merge(("root", root.path()))
|
||||
.merge((
|
||||
"template_dir",
|
||||
::std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("dist/templates")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"email_template_dir",
|
||||
::std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("dist/email-templates")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"assets_dir",
|
||||
::std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("dist/assets")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"keys_internal_dir",
|
||||
base_dir.join("keys_internal").to_str().unwrap(),
|
||||
))
|
||||
.merge((
|
||||
"keys_external_dir",
|
||||
base_dir.join("keys_external").to_str().unwrap(),
|
||||
))
|
||||
.merge(("tmp_dir", base_dir.join("tmp").to_str().unwrap()))
|
||||
.merge(("token_dir", base_dir.join("tokens").to_str().unwrap()))
|
||||
.merge((
|
||||
"maintenance_file",
|
||||
base_dir.join("maintenance").to_str().unwrap(),
|
||||
))
|
||||
.merge(("base-URI", BASE_URI))
|
||||
.merge(("base-URI-Onion", BASE_URI_ONION))
|
||||
.merge(("from", "from@example.com"))
|
||||
.merge(("token_secret", "hagrid"))
|
||||
.merge(("token_validity", 3600u64))
|
||||
.merge((
|
||||
"filemail_into",
|
||||
filemail
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("path is valid UTF8"),
|
||||
));
|
||||
Ok((root, config))
|
||||
}
|
||||
|
||||
fn rocket() -> anyhow::Result<(TempDir, rocket::Rocket<rocket::Build>)> {
|
||||
let (tmpdir, config) = configuration()?;
|
||||
|
||||
Ok((tmpdir, configure_rocket(rocket::custom(config))))
|
||||
}
|
||||
|
||||
pub fn client() -> anyhow::Result<(TempDir, Client)> {
|
||||
let (tmpdir, rocket) = rocket()?;
|
||||
|
||||
Ok((tmpdir, Client::untracked(rocket)?))
|
||||
}
|
||||
|
||||
pub fn assert_consistency(rocket: &rocket::Rocket<rocket::Orbit>) {
|
||||
pub fn assert_consistency(rocket: &::rocket::Rocket<::rocket::Orbit>) {
|
||||
let db = rocket.state::<Sqlite>().unwrap();
|
||||
db.check_consistency().unwrap();
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn about_translation() {
|
||||
let (_tmpdir, client) = client().expect("valid rocket instance");
|
||||
|
||||
fn about_translation(#[from(client)] (_tmpdir, client): (TempDir, Client)) {
|
||||
// Check that we see the landing page.
|
||||
let response = client
|
||||
.get("/about")
|
||||
@@ -464,9 +472,7 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn basics() {
|
||||
let (_tmpdir, client) = client().expect("valid rocket instance");
|
||||
|
||||
fn basics(#[from(client)] (_tmpdir, client): (TempDir, Client)) {
|
||||
// Check that we see the landing page.
|
||||
let response = client.get("/").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
@@ -517,9 +523,7 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn maintenance() {
|
||||
let (tmpdir, client) = client().unwrap();
|
||||
|
||||
fn maintenance(#[from(client)] (tmpdir, client): (TempDir, Client)) {
|
||||
let maintenance_path = tmpdir.path().join("maintenance");
|
||||
let mut file = File::create(&maintenance_path).unwrap();
|
||||
file.write_all(b"maintenance-message").unwrap();
|
||||
@@ -573,8 +577,8 @@ pub mod tests {
|
||||
base_uri: &str,
|
||||
base_uri_onion: &str,
|
||||
#[from(cert)] (cert_name, tpk): (&str, Cert),
|
||||
#[from(client)] (tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let (tmpdir, client) = client().unwrap();
|
||||
let filemail_into = tmpdir.path().join("filemail");
|
||||
|
||||
// Upload generated key.
|
||||
@@ -625,8 +629,10 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn upload_verify_lang(#[from(cert)] (cert_name, tpk): (&str, Cert)) {
|
||||
let (tmpdir, client) = client().unwrap();
|
||||
fn upload_verify_lang(
|
||||
#[from(cert)] (cert_name, tpk): (&str, Cert),
|
||||
#[from(client)] (tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let filemail_into = tmpdir.path().join("filemail");
|
||||
|
||||
// Upload it generated key.
|
||||
@@ -647,9 +653,8 @@ pub mod tests {
|
||||
#[with(alt_cert_name())]
|
||||
#[from(cert)]
|
||||
(cert_name_1, tpk_1): (&str, Cert),
|
||||
#[from(client)] (_tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let (_tmpdir, client) = client().expect("valid rocket instance");
|
||||
|
||||
// Upload generated keys.
|
||||
let mut tpk_serialized = Vec::new();
|
||||
tpk_0.serialize(&mut tpk_serialized).unwrap();
|
||||
@@ -679,8 +684,8 @@ pub mod tests {
|
||||
#[with(alt_cert_name())]
|
||||
#[from(cert)]
|
||||
(cert_name_2, tpk_2): (&str, Cert),
|
||||
#[from(client)] (tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let (tmpdir, client) = client().expect("valid rocket instance");
|
||||
let filemail_into = tmpdir.path().join("filemail");
|
||||
|
||||
// Upload generated keys.
|
||||
@@ -741,16 +746,18 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn upload_no_key() {
|
||||
let (_tmpdir, client) = client().unwrap();
|
||||
fn upload_no_key(#[from(client)] (_tmpdir, client): (TempDir, Client)) {
|
||||
let response = vks_publish_submit_response(&client, b"");
|
||||
|
||||
assert_eq!(response.status(), Status::BadRequest);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn upload_verify_onion(base_uri_onion: &str, #[from(cert)] (cert_name, tpk): (&str, Cert)) {
|
||||
let (tmpdir, client) = client().unwrap();
|
||||
fn upload_verify_onion(
|
||||
base_uri_onion: &str,
|
||||
#[from(cert)] (cert_name, tpk): (&str, Cert),
|
||||
#[from(client)] (tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let filemail_into = tmpdir.path().join("filemail");
|
||||
|
||||
// Upload generated key.
|
||||
@@ -783,9 +790,10 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn upload_curl_shortcut(#[from(cert)] (cert_name, tpk): (&str, Cert)) {
|
||||
let (_tmpdir, client) = client().unwrap();
|
||||
|
||||
fn upload_curl_shortcut(
|
||||
#[from(cert)] (cert_name, tpk): (&str, Cert),
|
||||
#[from(client)] (_tmpdir, client): (TempDir, Client),
|
||||
) {
|
||||
let mut tpk_serialized = Vec::new();
|
||||
tpk.serialize(&mut tpk_serialized).unwrap();
|
||||
|
||||
@@ -796,9 +804,7 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn search_invalid() {
|
||||
let (_tmpdir, client) = client().unwrap();
|
||||
|
||||
fn search_invalid(#[from(client)] (_tmpdir, client): (TempDir, Client)) {
|
||||
check_response(
|
||||
&client,
|
||||
"/search?q=0x1234abcd",
|
||||
@@ -825,9 +831,7 @@ pub mod tests {
|
||||
);
|
||||
}
|
||||
#[rstest]
|
||||
fn wkd_policy() {
|
||||
let (_tmpdir, client) = client().unwrap();
|
||||
|
||||
fn wkd_policy(#[from(client)] (_tmpdir, client): (TempDir, Client)) {
|
||||
check_response(
|
||||
&client,
|
||||
"/.well-known/openpgpkey/example.org/policy",
|
||||
|
Reference in New Issue
Block a user