mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 22:01:47 +00:00
170 lines
4.3 KiB
Rust
170 lines
4.3 KiB
Rust
pub mod criterion;
|
|
|
|
use std::fmt::{Display, Formatter};
|
|
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
|
|
use url::Url;
|
|
|
|
/// Relative size of a test case. Benchmarks can use it to configure the time for how long a benchmark should run to get stable results.
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
|
pub enum TestCaseSpeed {
|
|
/// A test case that is fast to run
|
|
Fast,
|
|
|
|
/// A normal test case
|
|
Normal,
|
|
|
|
/// A slow test case
|
|
Slow,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct TestCase {
|
|
file: TestFile,
|
|
speed: TestCaseSpeed,
|
|
}
|
|
|
|
impl TestCase {
|
|
pub fn fast(file: TestFile) -> Self {
|
|
Self {
|
|
file,
|
|
speed: TestCaseSpeed::Fast,
|
|
}
|
|
}
|
|
|
|
pub fn normal(file: TestFile) -> Self {
|
|
Self {
|
|
file,
|
|
speed: TestCaseSpeed::Normal,
|
|
}
|
|
}
|
|
|
|
pub fn slow(file: TestFile) -> Self {
|
|
Self {
|
|
file,
|
|
speed: TestCaseSpeed::Slow,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TestCase {
|
|
pub fn code(&self) -> &str {
|
|
&self.file.code
|
|
}
|
|
|
|
pub fn name(&self) -> &str {
|
|
&self.file.name
|
|
}
|
|
|
|
pub fn speed(&self) -> TestCaseSpeed {
|
|
self.speed
|
|
}
|
|
|
|
pub fn path(&self) -> PathBuf {
|
|
TARGET_DIR.join(self.name())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct TestFile {
|
|
name: String,
|
|
code: String,
|
|
}
|
|
|
|
static TARGET_DIR: once_cell::sync::Lazy<PathBuf> = once_cell::sync::Lazy::new(|| {
|
|
cargo_target_directory().unwrap_or_else(|| PathBuf::from("target"))
|
|
});
|
|
|
|
fn cargo_target_directory() -> Option<PathBuf> {
|
|
#[derive(serde::Deserialize)]
|
|
struct Metadata {
|
|
target_directory: PathBuf,
|
|
}
|
|
|
|
std::env::var_os("CARGO_TARGET_DIR")
|
|
.map(PathBuf::from)
|
|
.or_else(|| {
|
|
let output = Command::new(std::env::var_os("CARGO")?)
|
|
.args(["metadata", "--format-version", "1"])
|
|
.output()
|
|
.ok()?;
|
|
let metadata: Metadata = serde_json::from_slice(&output.stdout).ok()?;
|
|
Some(metadata.target_directory)
|
|
})
|
|
}
|
|
|
|
impl TestFile {
|
|
pub fn new(name: String, code: String) -> Self {
|
|
Self { name, code }
|
|
}
|
|
|
|
#[allow(clippy::print_stderr)]
|
|
pub fn try_download(name: &str, url: &str) -> Result<TestFile, TestFileDownloadError> {
|
|
let url = Url::parse(url)?;
|
|
|
|
let cached_filename = TARGET_DIR.join(name);
|
|
|
|
if let Ok(content) = std::fs::read_to_string(&cached_filename) {
|
|
Ok(TestFile::new(name.to_string(), content))
|
|
} else {
|
|
// File not yet cached, download and cache it in the target directory
|
|
let response = ureq::get(url.as_str()).call()?;
|
|
|
|
let content = response.into_string()?;
|
|
|
|
// SAFETY: There's always the `target` directory
|
|
let parent = cached_filename.parent().unwrap();
|
|
if let Err(error) = std::fs::create_dir_all(parent) {
|
|
eprintln!("Failed to crate the directory for the test case {name}: {error}");
|
|
} else if let Err(error) = std::fs::write(cached_filename, &content) {
|
|
eprintln!("Failed to cache test case file downloaded from {url}: {error}");
|
|
}
|
|
|
|
Ok(TestFile::new(name.to_string(), content))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum TestFileDownloadError {
|
|
UrlParse(url::ParseError),
|
|
Request(Box<ureq::Error>),
|
|
Download(std::io::Error),
|
|
}
|
|
|
|
impl From<url::ParseError> for TestFileDownloadError {
|
|
fn from(value: url::ParseError) -> Self {
|
|
Self::UrlParse(value)
|
|
}
|
|
}
|
|
|
|
impl From<ureq::Error> for TestFileDownloadError {
|
|
fn from(value: ureq::Error) -> Self {
|
|
Self::Request(Box::new(value))
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for TestFileDownloadError {
|
|
fn from(value: std::io::Error) -> Self {
|
|
Self::Download(value)
|
|
}
|
|
}
|
|
|
|
impl Display for TestFileDownloadError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
TestFileDownloadError::UrlParse(inner) => {
|
|
write!(f, "Failed to parse url: {inner}")
|
|
}
|
|
TestFileDownloadError::Request(inner) => {
|
|
write!(f, "Failed to download file: {inner}")
|
|
}
|
|
TestFileDownloadError::Download(inner) => {
|
|
write!(f, "Failed to download file: {inner}")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for TestFileDownloadError {}
|