Compare commits

..

No commits in common. "7bbb2bbc19d453c447f5f88105a9276ace9c9f1f" and "b3bccbbf65a59a2189ce0d36a64576a88db0088a" have entirely different histories.

7 changed files with 30 additions and 135 deletions

View file

@ -13,10 +13,7 @@
"configureZshAsDefaultShell": "true"
},
"ghcr.io/devcontainers/features/rust:1": {
"targets": "x86_64-unknown-linux-gnu,x86_64-unknown-linux-musl"
},
"ghcr.io/lee-orr/rusty-dev-containers/cargo-binstall:0": {
"packages": "cargo-llvm-cov"
"targets": "x86_64-unknown-linux-musl"
},
"ghcr.io/devcontainers-contrib/features/apt-get-packages:1": {
"packages": "git-flow, musl-tools"
@ -36,7 +33,7 @@
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "rustup target install x86_64-unknown-linux-musl | :",
"postCreateCommand": "rustup target install x86_64-unknown-linux-musl | :",
// Configure tool-specific properties.
"customizations": {
@ -46,8 +43,7 @@
},
"extensions": [
"mhutchie.git-graph",
"Gruntfuggly.todo-tree",
"ryanluker.vscode-coverage-gutters"
"Gruntfuggly.todo-tree"
]
}
},

4
.gitignore vendored
View file

@ -1,7 +1,3 @@
# code coverage reports
coverage/
# https://github.com/github/gitignore/raw/refs/heads/main/Rust.gitignore
# Generated by Cargo

54
.vscode/tasks.json vendored
View file

@ -5,6 +5,9 @@
"label": "Build Project",
"type": "cargo",
"command": "build",
// "presentation": {
// "reveal": "silent"
// },
"problemMatcher": "$rustc",
"group": "build"
},
@ -70,62 +73,13 @@
// "problemMatcher": "$rustc",
// "group": "test"
// },
{
"label": "Test Coverage",
"hide": true,
"type": "cargo",
"command": "llvm-cov",
"args": [],
"problemMatcher": "$rustc",
"group": "test",
},
{
"label": "Report Coverage (html)",
"hide": true,
"type": "cargo",
"command": "llvm-cov",
"args": [
"report",
"--html",
"--output-dir" ,
"coverage",
],
"problemMatcher": "$rustc",
"group": "test"
},
{
"label": "Report Coverage (lcov)",
"hide": true,
"type": "cargo",
"command": "llvm-cov",
"args": [
"report",
"--lcov",
"--output-path" ,
"coverage/lcov.info",
],
"problemMatcher": "$rustc",
"group": "test"
},
{
"label": "Run Coverage",
"type": "shell",
"dependsOn": [
"Test Coverage",
"Report Coverage (html)",
"Report Coverage (lcov)",
],
"dependsOrder": "sequence",
"group": "test"
},
{
"label": "Run All Tests",
"type": "shell",
"command": "echo All Tests successful!",
"dependsOn": [
"Run Unit Tests",
// "Run Integration Tests",
"Run Coverage",
// "Run Integration Tests"
],
"dependsOrder": "sequence",
"group": "test"

View file

@ -181,7 +181,7 @@ impl CacheFile {
.take()
.expect("abort_upload called while not uploading");
self.files.push_front(upl.stop());
self.files.push_front(upl.into());
}
pub fn share_notify(&self, client: &impl Client) -> crate::Result<()> {

View file

@ -115,27 +115,20 @@ impl FileTrait for Checked {
#[cfg(test)]
mod tests {
use tempfile::{NamedTempFile, TempDir};
use tempfile::TempDir;
use crate::test_util::{
MockClient, check_trait, create_file,
MockClient, create_file,
data::{HASHES_STD_GOOD, cases, data},
};
use super::*;
fn create_checked(content: &[u8]) -> (Checked, NamedTempFile) {
let file = create_file(content);
let chk = Checked::new(file.path()).expect("creating `Checked` should succeed");
// return both, so the `NamedTempFile` is not auto-deleted here
(chk, file)
}
#[test]
fn new_on_existing_file_works() {
for (content, size) in cases() {
let (chk, file) = create_checked(content);
let file = create_file(content);
let chk = Checked::new(file.path()).expect("creating `Checked` should succeed");
let path = file
.path()
@ -152,19 +145,6 @@ mod tests {
file.path().file_name().expect("`file_name` should succeed")
);
assert_eq!(chk.get_size(), size);
check_trait(
chk.as_ref(),
path.as_os_str().as_encoded_bytes(),
"AsRef<u8>",
"Checked",
);
// new_direct
let chk = Checked::new_direct(chk.path, chk.size, chk.hash);
assert_eq!(chk.path, path);
assert_eq!(chk.size, size);
assert!(chk.hash.is_none());
}
}
@ -199,7 +179,8 @@ mod tests {
#[test]
fn hashing_works() {
for (content, hash) in data().zip(HASHES_STD_GOOD) {
let (mut chk, _file) = create_checked(content);
let file = create_file(content);
let mut chk = Checked::new(file.path()).expect("creating `Checked` should succeed");
chk.hash(drop).expect("`hash` should succeed");
// `FileTrait`
@ -212,10 +193,10 @@ mod tests {
#[test]
fn hashing_again_errors() {
for content in data() {
let (mut chk, _file) = create_checked(content);
let file = create_file(content);
let mut chk = Checked::new(file.path()).expect("creating `Checked` should succeed");
// fake hash
chk.hash = Some(String::default());
chk.hash(drop).expect("`hash` should succeed");
let err = chk.hash(drop).expect_err("`hash` twice should fail");
assert!(err.is_mismatch("unhashed file", chk.path.display().to_string()));
@ -228,7 +209,8 @@ mod tests {
let share_id = client.add_share();
for content in data() {
let (chk, _file) = create_checked(content);
let file = create_file(content);
let chk = Checked::new(file.path()).expect("creating `Checked` should succeed");
assert!(
chk.start_upload(

View file

@ -1,19 +1,14 @@
use std::{any, fmt};
use std::fmt;
use crate::sharry;
/// Chunk of binary data belonging to a currently uploading file
pub struct Chunk<'t> {
/// id of the associated file
file_id: sharry::FileID,
/// offset of this chunk in bytes
offset: u64,
/// data inside this chunk
data: &'t [u8],
}
impl fmt::Debug for Chunk<'_> {
// chunks are 1 MiB or more, we shouldn't print that
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Chunk")
.field("file_id", &self.file_id)
@ -23,22 +18,6 @@ impl fmt::Debug for Chunk<'_> {
}
}
/// convert usize into other type
///
/// # Panics
///
/// - if the given value does not fit into the target type
fn from_usize_or_panic<I>(value: usize) -> I
where
I: TryFrom<usize>,
I::Error: std::error::Error,
{
value.try_into().unwrap_or_else(|e| {
let target_type = any::type_name::<I>();
panic!("usize={value:?} did not fit into {target_type:?}: {e}")
})
}
impl<'t> Chunk<'t> {
pub(super) fn new_direct(file_id: sharry::FileID, offset: u64, data: &'t [u8]) -> Self {
Self {
@ -65,10 +44,12 @@ impl<'t> Chunk<'t> {
/// get the chunk's length
pub fn get_length(&self) -> u64 {
// BOOKMARK this might **panic** on (hypothetical) platforms where `usize` has more than 64 bit.
let len = self.data.len();
// BOOKMARK this might **panic** on platforms where `usize` has more than 64 bit.
// Also, you've allocated more than 2 EiB ... in ONE chunk.
// Whoa! Maybe just chill?
from_usize_or_panic(self.data.len())
u64::try_from(len).unwrap_or_else(|e| panic!("usize={len} did not fit into u64: {e}"))
}
}
@ -104,17 +85,4 @@ mod tests {
assert_eq!(chunk.get_length(), len);
}
}
#[test]
#[should_panic(expected = "did not fit into \"u32\"")]
fn test_usize_overflow_panics() {
// works
assert_eq!(from_usize_or_panic::<u64>(usize::MAX), u64::MAX);
assert_eq!(from_usize_or_panic::<u32>(u32::MAX as usize), u32::MAX);
assert_eq!(from_usize_or_panic::<u16>(u16::MAX as usize), u16::MAX);
assert_eq!(from_usize_or_panic::<u8>(u8::MAX as usize), u8::MAX);
// panics
from_usize_or_panic::<u32>(usize::MAX);
}
}

View file

@ -32,6 +32,12 @@ pub struct Uploading {
offset: u64,
}
impl From<Uploading> for Checked {
fn from(value: Uploading) -> Self {
Self::new_direct(value.path, value.size, value.hash)
}
}
impl Uploading {
pub(super) fn new_direct(
path: PathBuf,
@ -112,13 +118,6 @@ impl Uploading {
Err(self.path)
}
}
/// stop uploading this file
///
/// - consume self, returning as a `file::Checked`
pub fn stop(self) -> Checked {
Checked::new_direct(self.path, self.size, self.hash)
}
}
impl FileTrait for Uploading {