feat: release Dever 0.1.4 with enforceable project guidance
This commit is contained in:
1 parent
201bdee372
commit
89629c2197
86 files changed
+2798
-338
No files matched your search
@@ -0,0 +1,132 @@
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use dever_core::{hir::Program, source::SourceMap};
|
||||
|
||||
#[path = "support/temp.rs"]
|
||||
mod temp;
|
||||
|
||||
fn examples() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../skills/assets/examples")
|
||||
}
|
||||
|
||||
fn checked(root: &Path) -> Program {
|
||||
let sources = SourceMap::load_project(&root.join("module"), &root.join("test")).unwrap();
|
||||
let settings = dever_runtime::config::Settings::load_project(root).unwrap();
|
||||
let program = dever_core::check_with_settings(&sources, &settings).unwrap_or_else(|errors| {
|
||||
panic!(
|
||||
"{}: {}",
|
||||
root.display(),
|
||||
errors
|
||||
.iter()
|
||||
.map(|error| error.render(&sources))
|
||||
.collect::<String>()
|
||||
)
|
||||
});
|
||||
let errors = program.application_errors().unwrap();
|
||||
assert!(
|
||||
errors.is_empty(),
|
||||
"{}",
|
||||
errors
|
||||
.iter()
|
||||
.map(|error| error.render(&sources))
|
||||
.collect::<String>()
|
||||
);
|
||||
program.validate_database_settings(&settings).unwrap();
|
||||
for source in sources.files() {
|
||||
assert_eq!(
|
||||
dever_core::format::format(source).unwrap(),
|
||||
source.text(),
|
||||
"{}",
|
||||
source.path().display()
|
||||
);
|
||||
}
|
||||
program
|
||||
}
|
||||
|
||||
fn copy_tree(source: &Path, target: &Path) {
|
||||
fs::create_dir(target).unwrap();
|
||||
for entry in fs::read_dir(source).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let destination = target.join(entry.file_name());
|
||||
if entry.file_type().unwrap().is_dir() {
|
||||
copy_tree(&entry.path(), &destination);
|
||||
} else {
|
||||
fs::copy(entry.path(), destination).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relocated_examples_check_production_roots_settings_and_case_local_effects() {
|
||||
let temporary = temp::TemporaryDirectory::new();
|
||||
let projects = [
|
||||
("http-rest", 1, false),
|
||||
("jobs", 1, true),
|
||||
("external-lib", 2, false),
|
||||
("collections", 2, false),
|
||||
("command", 1, false),
|
||||
];
|
||||
assert_eq!(fs::read_dir(examples()).unwrap().count(), projects.len());
|
||||
for (name, test_count, uses_database) in projects {
|
||||
let root = temporary.path().join(name);
|
||||
copy_tree(&examples().join(name), &root);
|
||||
let program = checked(&root);
|
||||
assert_eq!(program.tests().len(), test_count);
|
||||
assert!(
|
||||
program
|
||||
.tests()
|
||||
.iter()
|
||||
.all(|case| case.uses_database() == uses_database)
|
||||
);
|
||||
}
|
||||
let template = temporary.path().join("template");
|
||||
copy_tree(&examples().parent().unwrap().join("template"), &template);
|
||||
assert_eq!(checked(&template).tests().len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn three_ecosystems_share_one_checked_port_contract_and_fake_suite() {
|
||||
let temporary = temp::TemporaryDirectory::new();
|
||||
let root = temporary.path().join("external-lib");
|
||||
copy_tree(&examples().join("external-lib"), &root);
|
||||
let original = checked(&root).external_worker_contracts().remove(0);
|
||||
let mut schemas = std::collections::BTreeSet::new();
|
||||
for (ecosystem, entry, dependency) in [
|
||||
("pip", "python/render.py", "markdown@3.8.2"),
|
||||
("npm", "javascript/render.mjs", "marked@15.0.12"),
|
||||
("go", "go/render.go", "github.com/yuin/goldmark@v1.7.8"),
|
||||
] {
|
||||
fs::write(
|
||||
root.join("module/document/markup/adapter.dever"),
|
||||
format!("external {ecosystem} \"{entry}\" {{\n lib \"{dependency}\"\n}}\n"),
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(
|
||||
root.join("config/setting.json"),
|
||||
serde_json::to_vec(&serde_json::json!({
|
||||
"lib": [format!("{ecosystem}:{dependency}")]
|
||||
}))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let program = checked(&root);
|
||||
let contracts = program.external_worker_contracts();
|
||||
let [contract] = contracts.as_slice() else {
|
||||
panic!("one external Adapter must own the shared Port")
|
||||
};
|
||||
// 协议身份绑定生态和 Lib 声明;跨生态复用的是 Port 的类型合同。
|
||||
assert!(schemas.insert(contract.schema.clone()));
|
||||
assert_eq!(contract.port, original.port);
|
||||
assert_eq!(contract.setting, original.setting);
|
||||
assert_eq!(contract.inputs, original.inputs);
|
||||
assert_eq!(contract.outputs, original.outputs);
|
||||
assert_eq!(contract.errors, original.errors);
|
||||
assert_eq!(contract.operations, ["render"]);
|
||||
assert_eq!(contract.ecosystem, ecosystem);
|
||||
assert_eq!(contract.libs, [format!("{ecosystem}:{dependency}")]);
|
||||
assert!(root.join(&contract.entry).is_file());
|
||||
assert_eq!(program.tests().len(), 2);
|
||||
assert!(!program.tests().iter().any(|case| case.uses_database()));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user