diff --git a/src/cli.rs b/src/cli.rs index d465b58..928d611 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -4,6 +4,7 @@ //! the `Cli` struct that parses the command-line arguments and options. use clap::Parser; +use getset::CopyGetters; use crate::environment::Environment; @@ -12,10 +13,11 @@ use crate::environment::Environment; /// This command-line application can be used to run smoke tests against our infrastructure. The /// tests confirm that the infrastructure is working as expected and that no regressions have been /// introduced. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Parser)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, CopyGetters, Parser)] pub struct Cli { /// The environment to run the smoke tests against #[arg(long, value_enum, default_value_t)] + #[getset(get_copy = "pub")] env: Environment, } diff --git a/src/crates/issue_4891/config.rs b/src/crates/issue_4891/config.rs new file mode 100644 index 0000000..5fb7224 --- /dev/null +++ b/src/crates/issue_4891/config.rs @@ -0,0 +1,71 @@ +//! Configuration to test rust-lang/crates.io#4891 + +use getset::Getters; + +use crate::environment::Environment; + +/// Configuration to test rust-lang/crates.io#4891 +/// +/// The smoke tests try to access a crate with a `+` character in its version on all the different +/// Content Delivery Networks. The configuration provides a crate in the different environments that +/// can be used for the tests as well as the URLs for the CDNs. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, Getters)] +pub struct Config { + /// The name of the crate + #[get(get = "pub")] + krate: &'static str, + + /// The version with the `+` character + #[get(get = "pub")] + version: &'static str, + + /// The URL for the CloudFront CDN + #[get(get = "pub")] + cloudfront_url: &'static str, + + /// The URL for the Fastly CDN + #[get(get = "pub")] + fastly_url: &'static str, +} + +impl Config { + /// Return the configuration for the given environment + pub fn for_env(env: Environment) -> Self { + match env { + Environment::Staging => Self { + krate: "rust-cratesio-4891", + version: "0.1.0+1", + cloudfront_url: "https://cloudfront-static.staging.crates.io", + fastly_url: "https://fastly-static.staging.crates.io", + }, + Environment::Production => Self { + krate: "libgit2-sys", + version: "0.12.25+1.3.0", + cloudfront_url: "https://cloudfront-static.crates.io", + fastly_url: "https://fastly-static.crates.io", + }, + } + } +} + +#[cfg(test)] +mod tests { + use crate::test_utils::*; + + use super::*; + + #[test] + fn trait_send() { + assert_send::(); + } + + #[test] + fn trait_sync() { + assert_sync::(); + } + + #[test] + fn trait_unpin() { + assert_unpin::(); + } +} diff --git a/src/crates/issue_4891/mod.rs b/src/crates/issue_4891/mod.rs new file mode 100644 index 0000000..f288082 --- /dev/null +++ b/src/crates/issue_4891/mod.rs @@ -0,0 +1,74 @@ +//! Encoded URLs with a + sign fail + +use std::fmt::{Display, Formatter}; + +use crate::environment::Environment; +use crate::test::{TestGroup, TestGroupResult}; + +use self::config::Config; + +mod config; + +/// Encoded URLs with a + sign fail +/// +/// An issue was reported where requests that encoded the `+` character in the URL would receive an +/// HTTP 403 Forbidden response. The cause for this issue was that the `+` character has a special +/// meaning in S3, which was not considered when uploading crates in the past. The smoke tests +/// ensure that the Content Delivery Networks correctly rewrite the URL to avoid this issue. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] +pub struct Issue4891 { + /// Configuration for the test group + config: Config, +} + +impl Issue4891 { + /// Create a new instance of the test group + pub fn new(env: Environment) -> Self { + Self { + config: Config::for_env(env), + } + } +} + +impl Display for Issue4891 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "rust-lang/crates.io#4891") + } +} + +impl TestGroup for Issue4891 { + async fn run(&self) -> TestGroupResult { + todo!() + } +} + +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + + use crate::test_utils::*; + + use super::*; + + #[test] + fn trait_display() { + let issue_4891 = Issue4891::new(Environment::Staging); + + assert_eq!("rust-lang/crates.io#4891", issue_4891.to_string()); + } + + #[test] + fn trait_send() { + assert_send::(); + } + + #[test] + fn trait_sync() { + assert_sync::(); + } + + #[test] + fn trait_unpin() { + assert_unpin::(); + } +} diff --git a/src/crates/mod.rs b/src/crates/mod.rs index 32fd668..22abb48 100644 --- a/src/crates/mod.rs +++ b/src/crates/mod.rs @@ -2,7 +2,11 @@ use std::fmt::{Display, Formatter}; -use crate::test::{TestSuite, TestSuiteResult}; +use crate::crates::issue_4891::Issue4891; +use crate::environment::Environment; +use crate::test::{TestGroup, TestSuite, TestSuiteResult}; + +mod issue_4891; /// Smoke tests for crates.io /// @@ -10,7 +14,17 @@ use crate::test::{TestSuite, TestSuiteResult}; /// Delivery Network. The tests ensure that prior bugs in the configuration are not reintroduced, /// and that CloudFront and Fastly behave the same. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] -pub struct Crates {} +pub struct Crates { + /// The environment to run the tests in + env: Environment, +} + +impl Crates { + /// Creates a new instance of the test suite + pub fn new(env: Environment) -> Self { + Self { env } + } +} impl Display for Crates { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -20,9 +34,16 @@ impl Display for Crates { impl TestSuite for Crates { async fn run(&self) -> TestSuiteResult { + let groups = [Issue4891::new(self.env)]; + + let mut results = Vec::with_capacity(groups.len()); + for group in &groups { + results.push(group.run().await); + } + TestSuiteResult::builder() .name("crates.io") - .results(Vec::new()) + .results(results) .build() } } diff --git a/src/main.rs b/src/main.rs index 519fcb7..d3021b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,9 +25,9 @@ mod test_utils; #[tokio::main] async fn main() { - let _cli = Cli::parse(); + let cli = Cli::parse(); - let tests = vec![Crates::default()]; + let tests = vec![Crates::new(cli.env())]; let mut results: Vec = Vec::with_capacity(tests.len()); for test in &tests { diff --git a/src/test/mod.rs b/src/test/mod.rs index 86a36c6..4555444 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -1,5 +1,6 @@ //! Types that represent tests and their results +pub use self::test_group::TestGroup; pub use self::test_group_result::TestGroupResult; pub use self::test_result::TestResult; pub use self::test_suite::TestSuite;