Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,129 @@
|
||||
use super::{Directory, fixture};
|
||||
use dever::compiler::{build, project::Project};
|
||||
use dever_runtime::io::File;
|
||||
|
||||
mod stream;
|
||||
|
||||
#[test]
|
||||
fn file_aliases_share_cursor_and_close_without_truncating_existing_data() {
|
||||
let directory = Directory::new();
|
||||
let path = directory.0.join("file");
|
||||
let name = path.to_str().unwrap();
|
||||
let file = File::create(name).unwrap();
|
||||
file.write(b"abcde").unwrap();
|
||||
assert!(File::create(name).is_err());
|
||||
assert_eq!(std::fs::read(&path).unwrap(), b"abcde");
|
||||
file.close().unwrap();
|
||||
let file = File::open(name).unwrap();
|
||||
let alias = file.clone();
|
||||
assert_eq!(file.read(2).unwrap().unwrap(), b"ab");
|
||||
assert_eq!(alias.read(2).unwrap().unwrap(), b"cd");
|
||||
for limit in [0, -1, i64::MAX] {
|
||||
assert!(alias.read(limit).is_err());
|
||||
}
|
||||
assert_eq!(file.read(20).unwrap().unwrap(), b"e");
|
||||
assert_eq!(file.read(2).unwrap(), None);
|
||||
alias.close().unwrap();
|
||||
assert_eq!(file.read(2).unwrap_err(), "file is closed");
|
||||
assert_eq!(file.write(b"").unwrap_err(), "file is closed");
|
||||
assert_eq!(file.close().unwrap_err(), "file is closed");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn last_file_alias_releases_descriptor_on_success_and_error() {
|
||||
let directory = Directory::new();
|
||||
let path = directory.0.join("drop");
|
||||
std::fs::write(&path, b"test").unwrap();
|
||||
let open_count = || {
|
||||
std::fs::read_dir("/proc/self/fd")
|
||||
.unwrap()
|
||||
.filter_map(Result::ok)
|
||||
.filter(|entry| std::fs::read_link(entry.path()).ok().as_ref() == Some(&path))
|
||||
.count()
|
||||
};
|
||||
for _ in 0..32 {
|
||||
let alias = {
|
||||
let file = File::open(path.to_str().unwrap()).unwrap();
|
||||
let alias = file.clone();
|
||||
assert_eq!(open_count(), 1);
|
||||
alias
|
||||
};
|
||||
assert_eq!(open_count(), 1);
|
||||
drop(alias);
|
||||
assert_eq!(open_count(), 0);
|
||||
let failure = || -> Result<(), dever_runtime::io::Error> {
|
||||
let file = File::open(path.to_str().unwrap())?;
|
||||
let alias = file.clone();
|
||||
alias.read(0)?;
|
||||
Ok(())
|
||||
};
|
||||
assert!(failure().is_err());
|
||||
assert_eq!(open_count(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_file_values_preserve_aliases_and_nominal_failures() {
|
||||
let directory = Directory::new();
|
||||
std::fs::write(directory.0.join("input"), b"abcde").unwrap();
|
||||
let project = Project::load(&fixture().with_file_name("io.dever")).unwrap();
|
||||
let program = project.check().unwrap();
|
||||
for (entry, expected) in [
|
||||
("verify", None),
|
||||
("missing", Some("OpenResult.Failed")),
|
||||
("invalid", Some("ReadResult.Failed")),
|
||||
] {
|
||||
let binary =
|
||||
build::build(&program, &project.sources, entry, &directory.0.join(entry)).unwrap();
|
||||
let output = std::process::Command::new(binary)
|
||||
.current_dir(&directory.0)
|
||||
.output()
|
||||
.unwrap();
|
||||
if let Some(message) = expected {
|
||||
assert!(!output.status.success());
|
||||
assert!(output.stdout.is_empty());
|
||||
let error = String::from_utf8(output.stderr).unwrap();
|
||||
assert!(
|
||||
error.contains(message) && error.contains("lib/dever/io.dever:"),
|
||||
"{error}"
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
assert_eq!(output.stdout, b"hello\ntrue\n");
|
||||
assert_eq!(
|
||||
std::fs::read(directory.0.join("created")).unwrap(),
|
||||
b"hello"
|
||||
);
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let binary = build::build(
|
||||
&program,
|
||||
&project.sources,
|
||||
"print",
|
||||
&directory.0.join("print"),
|
||||
)
|
||||
.unwrap();
|
||||
let output = std::process::Command::new(binary)
|
||||
.stdout(
|
||||
std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.open("/dev/full")
|
||||
.unwrap(),
|
||||
)
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(!output.status.success());
|
||||
let error = String::from_utf8(output.stderr).unwrap();
|
||||
assert!(
|
||||
error.contains("standard output write failed") && error.contains("lib/dever/io.dever:"),
|
||||
"{error}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
use super::{Directory, File, fixture};
|
||||
use dever::compiler::{build, project::Project};
|
||||
|
||||
#[test]
|
||||
fn stream_aliases_continue_after_partial_reads_and_close_independently_of_file() {
|
||||
let directory = Directory::new();
|
||||
let path = directory.0.join("input");
|
||||
std::fs::write(&path, b"abcdef").unwrap();
|
||||
let file = File::open(path.to_str().unwrap()).unwrap();
|
||||
assert!(file.chunks(0, |value| value).is_err());
|
||||
let stream = file.chunks(2, |value| value).unwrap();
|
||||
let alias = stream.clone();
|
||||
assert_eq!(stream.next().unwrap().unwrap(), b"ab");
|
||||
assert_eq!(alias.next().unwrap().unwrap(), b"cd");
|
||||
alias.close();
|
||||
stream.close();
|
||||
assert!(stream.next().is_none());
|
||||
assert_eq!(file.read(2).unwrap().unwrap(), b"ef");
|
||||
let end = file.chunks(2, |value| value).unwrap();
|
||||
assert!(end.next().is_none());
|
||||
assert!(end.clone().next().is_none());
|
||||
file.close().unwrap();
|
||||
assert!(file.chunks(2, |value| value).is_err());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn terminal_stream_error_releases_source_before_returning_the_event() {
|
||||
let directory = Directory::new();
|
||||
let file = File::open(directory.0.to_str().unwrap()).unwrap();
|
||||
let stream = file.chunks(2, |value| value).unwrap();
|
||||
drop(file);
|
||||
let count = || {
|
||||
std::fs::read_dir("/proc/self/fd")
|
||||
.unwrap()
|
||||
.filter_map(Result::ok)
|
||||
.filter(|entry| std::fs::read_link(entry.path()).ok().as_ref() == Some(&directory.0))
|
||||
.count()
|
||||
};
|
||||
assert_eq!(count(), 1);
|
||||
assert!(stream.next().unwrap().is_err());
|
||||
assert_eq!(count(), 0);
|
||||
assert!(stream.next().is_none());
|
||||
assert!(stream.clone().next().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_stream_reduction_preserves_cursor_terminal_error_and_cleanup() {
|
||||
let directory = Directory::new();
|
||||
std::fs::write(directory.0.join("input"), b"abcdef").unwrap();
|
||||
let project = Project::load(&fixture().with_file_name("stream.dever")).unwrap();
|
||||
let program = project.check().unwrap();
|
||||
let binary = build::build(
|
||||
&program,
|
||||
&project.sources,
|
||||
"verify",
|
||||
&directory.0.join("verify"),
|
||||
)
|
||||
.unwrap();
|
||||
let output = std::process::Command::new(binary)
|
||||
.current_dir(&directory.0)
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
assert_eq!(output.stdout, b"true\n");
|
||||
}
|
||||
Reference in new issue
Block a user