Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,95 @@
|
||||
use dever::{
|
||||
compiler::{check, model::Program},
|
||||
syntax::{diagnostic::Diagnostic, source::Source},
|
||||
};
|
||||
|
||||
fn linked(text: &str) -> Result<Program, Diagnostic> {
|
||||
let inputs = [
|
||||
("main", text),
|
||||
(
|
||||
"dever.crypto",
|
||||
include_str!("../../../lib/dever/crypto.dever"),
|
||||
),
|
||||
("dever.time", include_str!("../../../lib/dever/time.dever")),
|
||||
("dever.task", include_str!("../../../lib/dever/task.dever")),
|
||||
];
|
||||
let modules = inputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, (_, text))| {
|
||||
dever::syntax::parse(&Source::new(
|
||||
index,
|
||||
if index == 0 {
|
||||
"main.dever".into()
|
||||
} else {
|
||||
format!("library{index}.dever")
|
||||
},
|
||||
(*text).into(),
|
||||
))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
check::check(
|
||||
modules,
|
||||
&inputs
|
||||
.iter()
|
||||
.map(|(package, _)| (*package).into())
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secrets_cannot_be_compared_converted_or_hidden_in_error_payloads() {
|
||||
for source in [
|
||||
"main(value: Secret) (answer: Bool) { answer = value == value }",
|
||||
"main(values: List<Secret>) (answer: Bool) { answer = values == values }",
|
||||
"main(value: Secret) (answer: Int) { answer = length(value) }",
|
||||
"main(value: Secret) (answer: Text) { answer = value }",
|
||||
"type Invalid { error Failed(value: Secret) }\nmain() () {}",
|
||||
"type Inner { key: Secret }\ntype Invalid { error Failed(values: List<Inner>) }\nmain() () {}",
|
||||
"main(values: Map<Secret, Int>) () {}",
|
||||
] {
|
||||
assert_eq!(linked(source).unwrap_err().code, "C005", "{source}");
|
||||
}
|
||||
let error = linked("main() () { value = secret(\"password\") }").unwrap_err();
|
||||
assert_eq!(error.code, "C006");
|
||||
assert!(error.message.contains("compiler-owned Test source"));
|
||||
assert!(linked("main(value: Secret) (answer: Secret?) { answer = value }").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crypto_randomness_and_password_work_keep_effect_boundaries() {
|
||||
for source in [
|
||||
"main() () pure { value = dever.crypto.token(16) }",
|
||||
"main(password: Secret) (hash: Text) { dever.task.sleep(0)\n hash = dever.crypto.passwordHash(password) }",
|
||||
"main(password: Secret, hash: Text) (valid: Bool) { dever.task.sleep(0)\n valid = dever.crypto.passwordVerify(password, hash) }",
|
||||
] {
|
||||
assert_eq!(linked(source).unwrap_err().code, "C013", "{source}");
|
||||
}
|
||||
assert!(linked("main(password: Secret) (hash: Text) { hash = blocking(dever.crypto.passwordHash(password)) }").is_ok());
|
||||
assert!(linked("main(key: Secret, bytes: Bytes) (hash: Bytes) pure { hash = dever.crypto.hmacSha256(key, bytes) }").is_ok());
|
||||
assert_eq!(
|
||||
linked("main() () { value = dever.system.cryptoToken(16) }")
|
||||
.unwrap_err()
|
||||
.code,
|
||||
"C006"
|
||||
);
|
||||
assert_eq!(
|
||||
linked("main() () { lost = result(dever.crypto.token(0)) }")
|
||||
.unwrap_err()
|
||||
.code,
|
||||
"C012"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_outputs_reject_nested_secret_types() {
|
||||
for source in [
|
||||
"read() (value: Secret?) { value = null }",
|
||||
"type Envelope { values: List<Secret> }\nread() (value: Envelope) { value = Envelope { values = [] } }",
|
||||
] {
|
||||
let module = dever::syntax::parse(&Source::new(0, "app.dever", source.into())).unwrap();
|
||||
let error = check::check(vec![module], &["shop.account.app".into()]).unwrap_err();
|
||||
assert_eq!(error.code, "C006");
|
||||
assert!(error.message.contains("Secret"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user