forked from matteo/serves3
Compare commits
1 Commits
main
...
mocking_an
Author | SHA1 | Date |
---|---|---|
Eren Ay | c554bdab6e |
|
@ -52,6 +52,18 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.82"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-stream"
|
name = "async-stream"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
@ -447,6 +459,12 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
|
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "downcast"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
|
@ -540,6 +558,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fragile"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fsevent-sys"
|
name = "fsevent-sys"
|
||||||
version = "4.1.0"
|
version = "4.1.0"
|
||||||
|
@ -620,6 +644,12 @@ version = "0.3.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
|
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-timer"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.29"
|
version = "0.3.29"
|
||||||
|
@ -1136,6 +1166,33 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mockall"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"downcast",
|
||||||
|
"fragile",
|
||||||
|
"lazy_static",
|
||||||
|
"mockall_derive",
|
||||||
|
"predicates",
|
||||||
|
"predicates-tree",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mockall_derive"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.39",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multer"
|
name = "multer"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
@ -1496,6 +1553,32 @@ version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"predicates-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-core"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-tree"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
|
||||||
|
dependencies = [
|
||||||
|
"predicates-core",
|
||||||
|
"termtree",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.70"
|
version = "1.0.70"
|
||||||
|
@ -1660,6 +1743,12 @@ version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "relative-path"
|
||||||
|
version = "1.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.22"
|
version = "0.11.22"
|
||||||
|
@ -1805,6 +1894,35 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rstest"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d5316d2a1479eeef1ea21e7f9ddc67c191d497abc8fc3ba2467857abbb68330"
|
||||||
|
dependencies = [
|
||||||
|
"futures",
|
||||||
|
"futures-timer",
|
||||||
|
"rstest_macros",
|
||||||
|
"rustc_version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rstest_macros"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04a9df72cc1f67020b0d63ad9bfe4a323e459ea7eb68e03bd9824db49f9a4c25"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"glob",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"relative-path",
|
||||||
|
"rustc_version",
|
||||||
|
"syn 2.0.39",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-ini"
|
name = "rust-ini"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
|
@ -1853,6 +1971,15 @@ version = "0.1.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.25"
|
version = "0.38.25"
|
||||||
|
@ -1931,6 +2058,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.193"
|
version = "1.0.193"
|
||||||
|
@ -1987,14 +2120,20 @@ dependencies = [
|
||||||
name = "serves3"
|
name = "serves3"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
"config",
|
"config",
|
||||||
"human-size",
|
"human-size",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"mockall",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_dyn_templates",
|
"rocket_dyn_templates",
|
||||||
|
"rstest",
|
||||||
"rust-s3",
|
"rust-s3",
|
||||||
"serde",
|
"serde",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2185,6 +2324,12 @@ dependencies = [
|
||||||
"unic-segment",
|
"unic-segment",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termtree"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.50"
|
version = "1.0.50"
|
||||||
|
@ -2261,9 +2406,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.34.0"
|
version = "1.37.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
|
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
|
@ -28,3 +28,11 @@ rocket_dyn_templates = { version = "0.1.0", features = ["tera"] }
|
||||||
rust-s3 = { version = "0.33", default-features = false, features = ["tokio-native-tls"] }
|
rust-s3 = { version = "0.33", default-features = false, features = ["tokio-native-tls"] }
|
||||||
serde = { version = "1.0" }
|
serde = { version = "1.0" }
|
||||||
tempfile = { version = "3.6" }
|
tempfile = { version = "3.6" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
|
async-trait = "0.1"
|
||||||
|
bytes = "1.5"
|
||||||
|
mockall = "0.12"
|
||||||
|
rstest = "0.19"
|
||||||
|
tokio = "1.37"
|
89
src/main.rs
89
src/main.rs
|
@ -2,13 +2,14 @@
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
// SPDX-License-Identifier: EUPL-1.2
|
||||||
|
|
||||||
use {
|
use {
|
||||||
lazy_static::lazy_static,
|
|
||||||
rocket::response::Responder,
|
rocket::response::Responder,
|
||||||
rocket::serde::Serialize,
|
rocket::serde::Serialize,
|
||||||
rocket_dyn_templates::{context, Template},
|
rocket_dyn_templates::{context, Template},
|
||||||
std::path::PathBuf,
|
std::path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
access_key_id: String,
|
access_key_id: String,
|
||||||
secret_access_key: String,
|
secret_access_key: String,
|
||||||
|
@ -67,7 +68,7 @@ lazy_static! {
|
||||||
.expect("Unable to create an empty temporary folder, is the whole FS read-only?");
|
.expect("Unable to create an empty temporary folder, is the whole FS read-only?");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Responder)]
|
#[derive(Responder, Debug)]
|
||||||
enum FileView {
|
enum FileView {
|
||||||
#[response(content_type = "text/html")]
|
#[response(content_type = "text/html")]
|
||||||
Folder(Template),
|
Folder(Template),
|
||||||
|
@ -78,6 +79,7 @@ enum FileView {
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct FileViewItem {
|
struct FileViewItem {
|
||||||
|
parent: String,
|
||||||
path: String,
|
path: String,
|
||||||
size: String,
|
size: String,
|
||||||
size_bytes: u64,
|
size_bytes: u64,
|
||||||
|
@ -159,7 +161,7 @@ async fn s3_fileview(path: &PathBuf) -> Result<Vec<FileViewItem>, Error> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let s3_objects = BUCKET
|
let s3_objects = BUCKET
|
||||||
.list(s3_folder_path, Some("/".into()))
|
.list(s3_folder_path.clone(), Some("/".into()))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| Error::NotFound("Object not found".into()))?;
|
.map_err(|_| Error::NotFound("Object not found".into()))?;
|
||||||
|
|
||||||
|
@ -175,6 +177,7 @@ async fn s3_fileview(path: &PathBuf) -> Result<Vec<FileViewItem>, Error> {
|
||||||
let folders = list.common_prefixes.iter().flatten().map(|dir| {
|
let folders = list.common_prefixes.iter().flatten().map(|dir| {
|
||||||
let path = dir.prefix.strip_prefix(&prefix);
|
let path = dir.prefix.strip_prefix(&prefix);
|
||||||
path.map(|path| FileViewItem {
|
path.map(|path| FileViewItem {
|
||||||
|
parent: s3_folder_path.clone(),
|
||||||
path: path.to_owned(),
|
path: path.to_owned(),
|
||||||
size_bytes: 0,
|
size_bytes: 0,
|
||||||
size: "[DIR]".to_owned(),
|
size: "[DIR]".to_owned(),
|
||||||
|
@ -185,6 +188,7 @@ async fn s3_fileview(path: &PathBuf) -> Result<Vec<FileViewItem>, Error> {
|
||||||
let files = list.contents.iter().map(|obj| {
|
let files = list.contents.iter().map(|obj| {
|
||||||
let path = obj.key.strip_prefix(&prefix);
|
let path = obj.key.strip_prefix(&prefix);
|
||||||
path.map(|path| FileViewItem {
|
path.map(|path| FileViewItem {
|
||||||
|
parent: s3_folder_path.clone(),
|
||||||
path: path.to_owned(),
|
path: path.to_owned(),
|
||||||
size_bytes: obj.size,
|
size_bytes: obj.size,
|
||||||
size: size_bytes_to_human(obj.size),
|
size: size_bytes_to_human(obj.size),
|
||||||
|
@ -238,3 +242,82 @@ fn rocket() -> _ {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test section starts
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use anyhow::Result;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use bytes::Bytes;
|
||||||
|
|
||||||
|
use rstest::rstest;
|
||||||
|
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||||
|
use super::*;
|
||||||
|
use mockall::mock;
|
||||||
|
use s3::{error::S3Error, request::ResponseData};
|
||||||
|
|
||||||
|
/// A trait implemented by a Struct we want to mock
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Bah {
|
||||||
|
async fn get_object<S: AsRef<str> + 'static + std::marker::Send>(
|
||||||
|
&self,
|
||||||
|
path: S,
|
||||||
|
) -> Result<ResponseData, S3Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
mock! {
|
||||||
|
pub Bucket {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Bah for Bucket {
|
||||||
|
async fn get_object<S: AsRef<str> + 'static + std::marker::Send>(&self, path: S) -> Result<ResponseData, S3Error>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(1024, "1.024 kB")]
|
||||||
|
#[case(10240, "10.240 kB")]
|
||||||
|
#[case(1024*1024, "1.049 MB")]
|
||||||
|
#[case(1024*1024*1024, "1.074 GB")]
|
||||||
|
#[case(0, "0.000 B")]
|
||||||
|
#[case(u64::MAX, format!("{:.3} GB",u64::MAX as f64/(1_000_000_000.0)))]
|
||||||
|
#[case(u64::MIN, format!("{:.3} B",u64::MIN as f64))]
|
||||||
|
|
||||||
|
fn test_size_bytes_to_human(#[case] bytes: u64, #[case] expected: String) {
|
||||||
|
println!("{}", size_bytes_to_human(bytes));
|
||||||
|
assert_eq!(size_bytes_to_human(bytes), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_s3_serve_file() -> Result<()>{
|
||||||
|
let mut mock_bucket = MockBucket::new();
|
||||||
|
|
||||||
|
mock_bucket.expect_get_object().times(1).returning(|_:String| {
|
||||||
|
panic!("here");
|
||||||
|
// Ok(ResponseData::new(
|
||||||
|
// Bytes::new(),
|
||||||
|
// 200,
|
||||||
|
// HashMap::<String, String>::new(),
|
||||||
|
// ))
|
||||||
|
});
|
||||||
|
|
||||||
|
let test_path: PathBuf = "foo".into();
|
||||||
|
|
||||||
|
let result = s3_serve_file(&test_path).await;
|
||||||
|
|
||||||
|
println!("{:?}", result);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let result = result.unwrap();
|
||||||
|
|
||||||
|
let bytes = match result {
|
||||||
|
FileView::File(b) => b,
|
||||||
|
_ => panic!("Should be a file."),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(bytes,vec![0]);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue