merge upstream testnet3

This commit is contained in:
gluax 2022-03-16 13:56:55 -07:00
commit 790c282e8b
55 changed files with 4299 additions and 573 deletions

View File

@ -46,7 +46,7 @@ commands:
jobs:
check-style:
docker:
- image: cimg/rust:1.56.1
- image: cimg/rust:1.59.0
resource_class: xlarge
steps:
- checkout
@ -61,7 +61,7 @@ jobs:
clippy:
docker:
- image: cimg/rust:1.56.1
- image: cimg/rust:1.59.0
resource_class: xlarge
steps:
- checkout
@ -76,7 +76,7 @@ jobs:
# code-cov:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# environment:
# RUSTC_BOOTSTRAP: 1
@ -118,7 +118,7 @@ jobs:
leo-executable:
docker:
- image: cimg/rust:1.56.1
- image: cimg/rust:1.59.0
resource_class: xlarge
steps:
- checkout
@ -136,7 +136,7 @@ jobs:
#
# leo-new:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -149,7 +149,7 @@ jobs:
#
# leo-init:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -162,7 +162,7 @@ jobs:
#
# leo-clean:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -175,7 +175,7 @@ jobs:
#
# leo-setup:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -188,7 +188,7 @@ jobs:
# leo-add-remove:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -202,7 +202,7 @@ jobs:
# todo (collin): uncomment after compiler refactor
# leo-check-constraints:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -215,7 +215,7 @@ jobs:
#
# leo-login-logout:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -228,7 +228,7 @@ jobs:
#
# leo-clone:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -241,7 +241,7 @@ jobs:
#
# leo-publish:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
/tmp/
**.idea/
*.DS_Store
.vscode
**/process.yml

8
Cargo.lock generated
View File

@ -1801,9 +1801,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.9"
version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525"
checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
dependencies = [
"base64",
"bytes",
@ -2665,9 +2665,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winreg"
version = "0.7.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [
"winapi 0.3.9",
]

View File

@ -82,7 +82,7 @@ version = "0.8"
version = "0.6.3"
[dependencies.reqwest]
version = "0.11.9"
version = "0.11.10"
features = [ "blocking", "json", "multipart" ]
[dependencies.self_update]

View File

@ -442,7 +442,7 @@ impl Canonicalizer {
match &console_function_call.function {
ConsoleFunction::Error(_) => ConsoleFunction::Error(console_args),
ConsoleFunction::Log(_) => ConsoleFunction::Log(console_args),
_ => unimplemented!(), // impossible
_ => unimplemented!(),
}
}
};

View File

@ -48,8 +48,8 @@ fn main() -> Result<(), String> {
let input_tree = create_session_if_not_set_then(|_| {
Handler::with(|handler| {
let input =
leo_parser::parse_program_inputs(&handler, input_string.clone(), opt.input_path.to_str().unwrap())?;
Ok(input.to_json_string()?)
leo_parser::parse_program_inputs(handler, input_string.clone(), opt.input_path.to_str().unwrap())?;
input.to_json_string()
})
.map_err(|e| e.to_string())
})?;

View File

@ -47,7 +47,7 @@ fn main() -> Result<(), String> {
// Parses the Leo file constructing an ast which is then serialized.
let serialized_leo_tree = create_session_if_not_set_then(|_| {
Handler::with(|h| {
let ast = leo_parser::parse_ast(&h, opt.input_path.to_str().unwrap(), &code)?;
let ast = leo_parser::parse_ast(h, opt.input_path.to_str().unwrap(), &code)?;
let json = Ast::to_json_string(&ast)?;
println!("{}", json);
Ok(json)

View File

@ -165,21 +165,15 @@ impl<'a> ParserContext<'a> {
/// the next token is not a [`GroupCoordinate`].
///
fn peek_group_coordinate(&self, i: &mut usize) -> Option<GroupCoordinate> {
if *i < 1 {
return None;
}
let token = self.tokens.get(*i - 1)?;
*i -= 1;
*i = i.checked_sub(1)?;
let token = self.tokens.get(*i)?;
Some(match &token.token {
Token::Add => GroupCoordinate::SignHigh,
Token::Minus if *i > 0 => match self.tokens.get(*i - 1) {
Token::Minus => match self.tokens.get(i.checked_sub(1)?) {
Some(SpannedToken {
token: Token::Int(value),
span,
}) => {
if *i < 1 {
return None;
}
*i -= 1;
GroupCoordinate::Number(format!("-{}", value), span.clone())
}
@ -212,57 +206,41 @@ impl<'a> ParserContext<'a> {
///
pub fn eat_group_partial(&mut self) -> Option<Result<(GroupCoordinate, GroupCoordinate, Span)>> {
let mut i = self.tokens.len();
if i < 1 {
return None;
}
let start_span = self.tokens.get(i - 1)?.span.clone();
let start_span = self.tokens.get(i.checked_sub(1)?)?.span.clone();
let first = self.peek_group_coordinate(&mut i)?;
if i < 1 {
i = i.checked_sub(1)?;
if !matches!(
self.tokens.get(i),
Some(SpannedToken {
token: Token::Comma,
..
})
) {
return None;
}
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::Comma, ..
}) => {
i -= 1;
}
_ => {
return None;
}
}
let second = self.peek_group_coordinate(&mut i)?;
if i < 1 {
i = i.checked_sub(1)?;
let right_paren_span = if let Some(SpannedToken {
token: Token::RightParen,
span,
}) = self.tokens.get(i)
{
span.clone()
} else {
return None;
}
let right_paren_span;
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::RightParen,
span,
}) => {
right_paren_span = span.clone();
i -= 1;
}
_ => {
return None;
}
}
if i < 1 {
};
i = i.checked_sub(1)?;
let end_span = if let Some(SpannedToken {
token: Token::Group,
span,
}) = self.tokens.get(i)
{
span.clone()
} else {
return None;
}
let end_span;
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::Group,
span,
}) => {
end_span = span.clone();
i -= 1;
}
_ => {
return None;
}
}
};
self.tokens.drain(i..);
if let Err(e) = assert_no_whitespace(

View File

@ -63,7 +63,7 @@ e.g. `<host, see [RFC3986], Section 3.2.2>`,
usable as last resort in the definiens of a nonterminal.
While BNF allows arbitrary terminals,
ABNF uses only natural numbers as terminals,
ABNF uses only natural numbers (i.e. non-negative integers) as terminals,
and denotes them via:
(i) binary, decimal, or hexadecimal sequences,
e.g. `%b1.11.1010`, `%d1.3.10`, and `%x.1.3.A`
@ -888,11 +888,12 @@ is a token, as defined by the following rule.
token = keyword
/ identifier
/ atomic-literal
/ numeral
/ annotation-name
/ symbol
```
Go to: _[annotation-name](#user-content-annotation-name), [atomic-literal](#user-content-atomic-literal), [identifier](#user-content-identifier), [keyword](#user-content-keyword), [symbol](#user-content-symbol)_;
Go to: _[annotation-name](#user-content-annotation-name), [atomic-literal](#user-content-atomic-literal), [identifier](#user-content-identifier), [keyword](#user-content-keyword), [numeral](#user-content-numeral), [symbol](#user-content-symbol)_;
Tokens, comments, and whitespace are lexemes, i.e. lexical units.

View File

@ -588,6 +588,7 @@ symbol = "!" / "&" / "&&" / "||"
token = keyword
/ identifier
/ atomic-literal
/ numeral
/ annotation-name
/ symbol

View File

@ -195,7 +195,7 @@ impl TryFrom<&Path> for Manifest {
if line.starts_with("remote") {
let remote = line
.split('=') // Split the line as 'remote' = '"{author}/{package_name}"'
.collect::<Vec<&str>>()[1]; // Fetch just '"{author}/{package_name}"'
.nth(1).unwrap(); // Fetch just '"{author}/{package_name}"'
old_remote_format = Some(remote);
// Retain the old remote format if the `manifest_refactor_remote` is not enabled
@ -238,8 +238,8 @@ impl TryFrom<&Path> for Manifest {
// Fetch the author from the old remote.
let remote_author = old_remote
.split('/') // Split the old remote as '"{author}' and '{package_name}"'
.collect::<Vec<&str>>()[0] // Fetch just the '"{author}'
.replace(&['\"', ' '][..], ""); // Remove the quotes from the author string
.next().unwrap() // Fetch just the '"{author}'
.replace(&['\"', ' '], ""); // Remove the quotes from the author string
// Construct the new remote section.
let new_remote = format!(

View File

@ -88,7 +88,7 @@ impl Serialize for Span {
} else {
state.serialize_field("path", "")?;
}
state.serialize_field("content", &self.content[..])?;
state.serialize_field("content", &self.content)?;
state.end()
}
}

View File

@ -21,7 +21,7 @@ use tendril::StrTendril;
/// Serialization for the StrTendril type.
pub fn serialize<S: Serializer>(tendril: &StrTendril, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&tendril[..])
serializer.serialize_str(tendril)
}
/// Deserialization for the StrTendril type.

View File

@ -5,6 +5,7 @@ outputs:
- "''a'' @ 1:1-4"
- "''Z'' @ 1:1-4"
- "''\"'' @ 1:1-5"
- "''''' @ 1:1-5"
- "''\t'' @ 1:1-5"
- "''\r'' @ 1:1-5"
- "''\u0000'' @ 1:1-5"
@ -14,6 +15,7 @@ outputs:
- "''å'' @ 1:1-5"
- "''Ӡ'' @ 1:1-10"
- "''Ӡ'' @ 1:1-5"
- "''D800'' @ 1:1-11"
- "''❤'' @ 1:1-11"
- "''❤'' @ 1:1-6"
- "''😢'' @ 1:1-12"

View File

@ -3,12 +3,15 @@ namespace: Token
expectation: Fail
outputs:
- "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370032]: Could not lex the following content: `\\`."
- "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370032]: Could not lex the following content: `\\n`."
- "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370036]: Expected a valid hex character but found `'`."
- "Error [EPAR0370036]: Expected a valid hex character but found `'`."
- "Error [EPAR0370036]: Expected a valid hex character but found `9A`."
- "Error [EPAR0370036]: Expected a valid hex character but found `'`."
- "Error [EPAR0370036]: Expected a valid hex character but found `7g`."
- "Error [EPAR0370036]: Expected a valid hex character but found `'`."
- "Error [EPAR0370036]: Expected a valid hex character but found `80`."
- "Error [EPAR0370036]: Expected a valid hex character but found `c1`."
- "Error [EPAR0370036]: Expected a valid hex character but found `c2`."
@ -17,7 +20,6 @@ outputs:
- "Error [EPAR0370036]: Expected a valid hex character but found `e0`."
- "Error [EPAR0370036]: Expected a valid hex character but found `9f`."
- "Error [EPAR0370027]: Expected a closed string but found `'b'`."
- "Error [EPAR0370027]: Expected a closed string but found `'\\\\'`."
- "Error [EPAR0370026]: Expected a valid escape character but found `a`."
- "Error [EPAR0370026]: Expected a valid escape character but found `z`."
- "Error [EPAR0370026]: Expected a valid escape character but found `A`."
@ -30,15 +32,17 @@ outputs:
- "Error [EPAR0370027]: Expected a closed string but found `'\\\\'`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `z`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `1`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `}`."
- "Error [EPAR0370027]: Expected a closed string but found `'\\\\'`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `1`."
- "Error [EPAR0370027]: Expected a closed string but found `'1'`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `6`."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `af🦀'`."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `2764z'`."
- "Error [EPAR0370036]: Expected a valid hex character but found `276g`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `0`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `0`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `9`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `0`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `0`."
- "Error [EPAR0370039]: The escaped unicode char `110000` is greater than 0x10FFFF."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `}`."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `af🦀'`."
- "Error [EPAR0370027]: Expected a closed string but found `'\\\\'`."
- "Error [EPAR0370027]: Expected a closed string but found `'1'`."
- "Error [EPAR0370027]: Expected a closed string but found `'😂'`."

View File

@ -0,0 +1,15 @@
---
namespace: ParseExpression
expectation: Fail
outputs:
- "Error [EPAR0370030]: Empty block comment."
- "Error [EPAR0370031]: Block comment does not close with content: `/* test`."
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '/'\n --> test:1:1\n |\n 1 | / /\n | ^"
- "Error [EPAR0370031]: Block comment does not close with content: `/*/`."
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '*'\n --> test:1:1\n |\n 1 | */\n | ^"
- "Error [EPAR0370032]: Could not lex the following content: `🦀**/`."
- "Error [EPAR0370032]: Could not lex the following content: `🦀*/`."
- "Error [EPAR0370031]: Block comment does not close with content: `/*🦀/`."
- "Error [EPAR0370031]: Block comment does not close with content: `/**🦀`."
- "Error [EPAR0370031]: Block comment does not close with content: `/*🦀`."
- "Error [EPAR0370031]: Block comment does not close with content: `/*/*`."

View File

@ -680,3 +680,35 @@ outputs:
col_stop: 16
path: ""
content: "(123, 456)group"
- Value:
Group:
Single:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: 1group
- Unary:
inner:
Value:
Group:
Single:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 2
col_stop: 8
path: ""
content: "-1group"
op: Negate
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "-1group"

View File

@ -10,3 +10,7 @@ outputs:
- "did not consume all input: 'group' @ 1:6-11\n"
- "did not consume all input: 'group' @ 1:12-17\n"
- "did not consume all input: 'group' @ 1:15-20\n"
- "Error [EPAR0370004]: Unexpected white space between terms (123,456) and group\n --> test:1:10\n |\n 1 | (123, 456) group\n | ^"
- "did not consume all input: 'group' @ 1:8-13\n"
- "did not consume all input: 'group' @ 1:16-21\n"
- "did not consume all input: 'bool' @ 1:11-15\n"

View File

@ -0,0 +1,7 @@
---
namespace: Token
expectation: Fail
outputs:
- "Error [EPAR0370040]: A hex number `0x..` was provided but hex is not allowed."
- "Error [EPAR0370040]: A hex number `0x..` was provided but hex is not allowed."
- "Error [EPAR0370040]: A hex number `0x..` was provided but hex is not allowed."

View File

@ -32,6 +32,16 @@ outputs:
col_stop: 9
path: ""
content: 456field
- Value:
Implicit:
- ""
- span:
line_start: 0
line_stop: 0
col_start: 0
col_stop: 0
path: ""
content: ""
- Value:
Field:
- "87377802873778028737780287377802873778028737780287377802873778028737780287377802"

View File

@ -2,7 +2,6 @@
namespace: Token
expectation: Pass
outputs:
- "'\"\"' @ 1:1-3"
- "'\"string\"' @ 1:1-9"
- "'\"another { } string\"' @ 1:1-21"
- "'\"{ ] [ ; a\"' @ 1:1-12"
@ -14,6 +13,19 @@ outputs:
- "'\"\n\"' @ 1:1-8"
- "'\"\n\"' @ 1:1-7"
- "'\"\u007f\"' @ 1:1-7"
- "'\"aa \\ \" \n aa \t \r \u0000\"' @ 1:1-28"
- "'\"aa \\ \" ' \n aa \t \r \u0000\"' @ 1:1-30"
- "'\"test 😒€\"' @ 1:1-15"
- "'\"😭😂😘\"' @ 1:1-15"
- "'\"✋🏿\"' @ 1:1-10"
- "'\"🦀\"' @ 1:1-7"
- "'\"￿\"' @ 1:1-6"
- "'\"<22><><EFBFBD>\"' @ 1:1-12"
- "'\"><)三\"' @ 1:1-17"
- "'\"ヽ༼ ಠ益ಠ ༽ノ\"' @ 1:1-26"
- "'\"(╯°□°)╯︵ ┻━┻\"' @ 1:1-33"
- "'\"┬─┬ ( ゜-゜ノ)\"' @ 1:1-29"
- "'\"( ͡° ͜ʖ ͡°)\"' @ 1:1-20"
- "'\"b\"' @ 1:1-4,'// TODO reenabe once #1682 is closed \"ᕙ(▀̿ĺ̯▀̿ ̿)ᕗ\"' @ 1:5-69"
- "'\"♥╣[-_-]╠♥\"' @ 1:1-20"
- "'\"b\"' @ 1:1-4,'// TODO reenabe once #1682 is closed \"(⑅∫°ਊ°)∫\"' @ 1:5-62"
- "'\"b\"' @ 1:1-4,'// TODO reenabe once #1682 is closed \"🦀°1\"' @ 1:5-51"

View File

@ -4,6 +4,7 @@ expectation: Fail
outputs:
- "Error [EPAR0370027]: Expected a closed string but found `[Scalar('H'), Scalar('e'), Scalar('l'), Scalar('l'), Scalar('o'), Scalar(' '), Scalar('w'), Scalar('o'), Scalar('r'), Scalar('l'), Scalar('d'), Scalar('!')]`."
- "Error [EPAR0370027]: Expected a closed string but found `[Scalar('\"')]`."
- "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370026]: Expected a valid escape character but found `l`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `a`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `\"`."
@ -11,3 +12,5 @@ outputs:
- "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `}`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `6`."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `af🦀\"`."
- "Error [EPAR0370032]: Could not lex the following content: `⭇😍;`."

View File

@ -122,3 +122,24 @@ outputs:
col_stop: 4
path: ""
content: "-!x"
- Value:
Implicit:
- "-5"
- span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 3
path: ""
content: "-5"
- Value:
Integer:
- I8
- "-5"
- span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "-5i8"

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370003]: unexpected EOF\n --> test:3:1\n |\n 3 | const\n | ^^^^^"

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370032]: Could not lex the following content: `\\`."

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
---
namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x::y = y;\n | ^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | 5 = y;\n | ^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x + x = y;\n | ^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | -x = y;\n | ^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | !x = y;\n | ^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | a? x : x = y;\n | ^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x as u32 = y;\n | ^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | [x, x, x] = y;\n | ^^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | [x; 3] = y;\n | ^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | (x, x, x) = y;\n | ^^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x {x: y, y: z} = y;\n | ^^^^^^^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x() = y;\n | ^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x.y() = y;\n | ^^^^^"
- "Error [EPAR0370032]: Could not lex the following content: `🦀 = y;`."

View File

@ -0,0 +1,6 @@
---
namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370009]: unexpected string: expected 'formatted string', got '1'\n --> test:1:13\n |\n 1 | console.log(1);\n | ^"
- "Error [EPAR0370007]: unexpected identifier: expected 'assert', 'error', 'log' -- got 'test'\n --> test:1:9\n |\n 1 | console.test();\n | ^^^^"

View File

@ -1540,3 +1540,132 @@ outputs:
col_stop: 37
path: ""
content: "let x: [[u8; 2]; 2] = [[0,0], [0,0]];"
- Definition:
declaration_type: Let
variable_names:
- mutable: true
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"let x: [u8; (2, 2)] = [[0,0], [0,0]];\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
type_:
Array:
- IntegerType: U8
- - value: "2"
- value: "2"
value:
ArrayInline:
elements:
- Expression:
ArrayInline:
elements:
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 25
col_stop: 26
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 27
col_stop: 28
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 24
col_stop: 29
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Expression:
ArrayInline:
elements:
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 32
col_stop: 33
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 34
col_stop: 35
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 31
col_stop: 36
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 23
col_stop: 37
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 37
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Definition:
declaration_type: Let
variable_names:
- mutable: true
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;"
type_: Address
value:
Value:
Address:
- aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53
- span:
line_start: 1
line_stop: 1
col_start: 18
col_stop: 81
path: ""
content: "let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 81
path: ""
content: "let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;"

View File

@ -25,5 +25,24 @@ outputs:
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:10\n |\n 1 | let (x,y,,) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:6\n |\n 1 | let (,x,y) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:8\n |\n 1 | let (x,,y) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'int', got ','\n --> test:1:16\n |\n 1 | let x: [u8; (2,,)] = [[0,0], [0,0]];\n | ^\nError [EPAR0370045]: do not put parens around single dimension array size\n --> test:1:13\n |\n 1 | let x: [u8; (2,,)] = [[0,0], [0,0]];\n | ^^^^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got 'const'\n --> test:1:8\n |\n 1 | let x: const = expr;\n | ^^^^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got 'let'\n --> test:1:10\n |\n 1 | const x: let = expr;\n | ^^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got 'mut'\n --> test:1:8\n |\n 1 | let x: mut = expr;\n | ^^^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:1\n |\n 1 | let\n | ^^^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:5\n |\n 1 | let x\n | ^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:6\n |\n 1 | let x:\n | ^"
- "Error [EPAR0370005]: expected ) -- got ']'\n --> test:1:14\n |\n 1 | let x = (a, y]);\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '='\n --> test:1:5\n |\n 1 | let = 1u8;\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ';'\n --> test:1:4\n |\n 1 | let;\n | ^"
- "Error [EPAR0370005]: expected = -- got '1'\n --> test:1:7\n |\n 1 | let x 1u8;\n | ^"
- "Error [EPAR0370005]: expected = -- got ';'\n --> test:1:10\n |\n 1 | let x: u8;\n | ^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:8\n |\n 1 | let x: u8\n | ^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got '='\n --> test:1:8\n |\n 1 | let x: = 1;\n | ^"
- "Error [EPAR0370005]: expected ; -- got ']'\n --> test:1:11\n |\n 1 | let x: [u8] = 1;\n | ^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:11\n |\n 1 | let x: [u8;\n | ^"
- "Error [EPAR0370005]: expected ] -- got 'u8'\n --> test:1:14\n |\n 1 | let x: [u8; 1u8] = [1,\n | ^^"
- "Error [EPAR0370009]: unexpected string: expected 'expression', got ']'\n --> test:1:15\n |\n 1 | let dbg: u8 = ];\n | ^"
- "Error [EPAR0370032]: Could not lex the following content: `🦀: u8 = 0;`."
- "Error [EPAR0370044]: do not put parens around single variable names\n --> test:1:6\n |\n 1 | let (x) = ...;\n | ^\nError [EPAR0370009]: unexpected string: expected 'expression', got '...'\n --> test:1:11\n |\n 1 | let (x) = ...;\n | ^^^"
- "Error [EPAR0370044]: do not put parens around single variable names\n --> test:1:6\n |\n 1 | let (x,) = ...;\n | ^\nError [EPAR0370009]: unexpected string: expected 'expression', got '...'\n --> test:1:12\n |\n 1 | let (x,) = ...;\n | ^^^"

View File

@ -0,0 +1,10 @@
---
namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370009]: unexpected string: expected 'expression', got ']'\n --> test:1:2\n |\n 1 | (];\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'expression', got ')'\n --> test:1:2\n |\n 1 | [);\n | ^"
- "Error [EPAR0370032]: Could not lex the following content: `\\y;`."
- "Error [EPAR0370046]: Found the char `;`, but expected `|`"
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '}'\n --> test:1:3\n |\n 1 | x[};\n | ^"
- "Error [EPAR0370005]: expected ) -- got ']'\n --> test:1:6\n |\n 1 | (x, y];\n | ^"

View File

@ -11,4 +11,4 @@ x[x][y][z]
x[0]()
x()[0]
x(y)::y(x)
x[x].0[x]
x[x].0[x]

View File

@ -6,6 +6,7 @@ expectation: Pass
'a'
'Z'
'\"'
'\''
'\t'
'\r'
'\0'
@ -15,6 +16,7 @@ expectation: Pass
'å'
'\u{4e0}'
'Ӡ'
'\u{d800}'
'\u{2764}'
'❤'
'\u{1F622}'

View File

@ -4,15 +4,18 @@ expectation: Fail
*/
'\'
\
'\
\n
'a
''
'\x9A'
'\x7'
'\x7g'
'\xz'
'\x9A'
'\x7g'
'\x80'
'\xc1'
'\xc2'
@ -23,7 +26,6 @@ expectation: Fail
'abcdefg'
'\t\t'
'\a'
'\z'
'\A'
@ -33,20 +35,22 @@ expectation: Fail
'\*'
'\x'
'\u'
'\t\t'
'\u{bbbbb}\u{aaaa}'
'\uz'
'\u1'
'\u};
'🦀\n'
'\u123'
'🦀1🦀'
'\u6🦀}'
'\u{af🦀'
'\u{2764z'
'\u{276g}'
'\u9999999'
'\u00000000'
'\u01000000'
'\u9999999'
'\u{110000}'
'\u}'
'\u{bbbbb}\u{aaaa}'
'\u{af🦀'
'🦀\n'
'🦀1🦀'
'😭😂😘'

View File

@ -0,0 +1,26 @@
/*
namespace: ParseExpression
expectation: Fail
*/
/*
/* test
/ /
/*/
*/
🦀**/
/🦀*/
/*🦀/
/**🦀
/*🦀
/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*

View File

@ -66,3 +66,7 @@ expectation: Pass
(123, 456)group
(123, 456)group
1group
-1group

View File

@ -18,3 +18,11 @@ expectation: Fail
(123,456u8)group
(123,456field)group
(123, 456) group
(123, )group
(123, 456, 789)group
(123, 456)bool

View File

@ -0,0 +1,8 @@
/*
namespace: Token
expectation: Fail
*/
0xb
0x
0xbfield

View File

@ -8,6 +8,8 @@ expectation: Pass
123
456field
// 0xbfield
87377802873778028737780287377802873778028737780287377802873778028737780287377802field
8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802field

View File

@ -3,112 +3,112 @@ namespace: ParseExpression
expectation: Pass
*/
123u8
123u16
123
456u8
456u16
87377802873778028737780287377802873778028737780287377802873778028737780287377802u8
87377802873778028737780287377802873778028737780287377802873778028737780287377802u16
8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802u8
8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802u16
340130024u8
158951116u8
155529659u8
642023166u8
228481736u8
469712960u8
929437719u8
721072814u8
363254789u8
906732565u8
288246391u8
724940549u8
487101620u8
261373583u8
891163927u8
743967544u8
8372586u8
461793278u8
806307045u8
122764546u8
356336181u8
158370903u8
774460877u8
557174131u8
492401267u8
893445620u8
957757048u8
721540649u8
390746493u8
211251725u8
938266114u8
156985870u8
703831126u8
729964155u8
988151305u8
320872435u8
719287167u8
152289486u8
740067975u8
728627816u8
385008978u8
553967635u8
71980713u8
519444716u8
116499965u8
717422268u8
18966279u8
22458638u8
857282620u8
920675898u8
762235516u8
469018377u8
199986521u8
536679358u8
591399452u8
83083158u8
599449051u8
445442318u8
585486590u8
209278800u8
873568117u8
664470940u8
465262783u8
605652874u8
376803940u8
965247040u8
598474509u8
845119918u8
648159133u8
669051032u8
800600261u8
434689764u8
520060080u8
804659385u8
537828058u8
716600292u8
387020273u8
199375617u8
680337189u8
818479931u8
893693281u8
87377802u8
84699261u8
292826090u8
569171405u8
387436237u8
150682190u8
888770419u8
824696431u8
765659803u8
270163693u8
427940240u8
504997332u8
337808338u8
907200008u8
757177889u8
696697188u8
41376051u8
496293518u8
251218820u8
340130024u16
158951116u16
155529659u16
642023166u16
228481736u16
469712960u16
929437719u16
721072814u16
363254789u16
906732565u16
288246391u16
724940549u16
487101620u16
261373583u16
891163927u16
743967544u16
8372586u16
461793278u16
806307045u16
122764546u16
356336181u16
158370903u16
774460877u16
557174131u16
492401267u16
893445620u16
957757048u16
721540649u16
390746493u16
211251725u16
938266114u16
156985870u16
703831126u16
729964155u16
988151305u16
320872435u16
719287167u16
152289486u16
740067975u16
728627816u16
385008978u16
553967635u16
71980713u16
519444716u16
116499965u16
717422268u16
18966279u16
22458638u16
857282620u16
920675898u16
762235516u16
469018377u16
199986521u16
536679358u16
591399452u16
83083158u16
599449051u16
445442318u16
585486590u16
209278800u16
873568117u16
664470940u16
465262783u16
605652874u16
376803940u16
965247040u16
598474509u16
845119918u16
648159133u16
669051032u16
800600261u16
434689764u16
520060080u16
804659385u16
537828058u16
716600292u16
387020273u16
199375617u16
680337189u16
818479931u16
893693281u16
87377802u16
84699261u16
292826090u16
569171405u16
387436237u16
150682190u16
888770419u16
824696431u16
765659803u16
270163693u16
427940240u16
504997332u16
337808338u16
907200008u16
757177889u16
696697188u16
41376051u16
496293518u16
251218820u16

View File

@ -3,8 +3,6 @@ namespace: Token
expectation: Pass
*/
""
"string"
"another { } string"
@ -22,7 +20,23 @@ expectation: Pass
"\x7F"
"aa \\ \" \n aa \t \r \0"
"aa \\ \" \' \n aa \t \r \0"
"test 😒€"
"😭😂😘"
"😭😂😘"
"✋🏿"
"🦀"
"￿"
"<22><><EFBFBD>"
"><)三"
"ヽ༼ ಠ益ಠ ༽ノ"
"(╯°□°)╯︵ ┻━┻"
"┬─┬ ( ゜-゜ノ)"
"( ͡° ͜ʖ ͡°)"
"b" // TODO reenabe once #1682 is closed "ᕙ(▀̿ĺ̯▀̿ ̿)ᕗ"
"♥╣[-_-]╠♥"
"b" // TODO reenabe once #1682 is closed "(⑅∫°ਊ°)∫"
"b" // TODO reenabe once #1682 is closed "🦀°1"

View File

@ -7,6 +7,8 @@ expectation: Fail
"\"
"\
"\l"
"\uaaa"
@ -19,4 +21,8 @@ expectation: Fail
"\u}"
"\u6🦀}"
"\u6🦀}"
"\u{af🦀"
"\" // TODO reenable once #1683 is closed "⭇😍;

View File

@ -1,26 +0,0 @@
/*
namespace: ParseExpression
expectation: Pass
*/
"string"
"another { } string"
"{ ] [ ; a"
"\u{FFA}"
"\u{afafa}"
"\u{afaf}"
"\u{afa}"
"\u{af}"
"\u{a}"
"\x0A"
"\x7F"
"aa \\ \" \n aa \t \r \0"
"test 😒€"
"😭😂😘"

View File

@ -9,3 +9,6 @@ expectation: Pass
-x()
--x
-!x
-5
-5i8

View File

@ -0,0 +1,6 @@
/*
namespace: Parse
expectation: Fail
*/
const

View File

@ -0,0 +1,9 @@
/*
namespace: Parse
expectation: Fail
*/
function main() {
let x = 1u8;
}
\

View File

@ -29,3 +29,162 @@ x[2..] = y;
x[..] = y;
x.0[0][..] = y;
x.y = y;
x.0.y[0].1.y[..][0][1..5][0..3] = y;
x += expr;
x += ();
x += x+y;
x += x();
x[0] += y;
x[0u32] += y;
x.0 += y;
x[1..2][0] += y;
x[..2][0] += y;
x[2..][0] += y;
x[..][0] += y;
x.0[0][..][0] += y;
x.y += y;
x.0.y[0].1.y[..][0][1..5][0..3][0] += y;
x -= expr;
x -= ();
x -= x+y;
x -= x();
x[0] -= y;
x[0u32] -= y;
x.0 -= y;
x[1..2][0] -= y;
x[..2][0] -= y;
x[2..][0] -= y;
x[..][0] -= y;
x.0[0][..][0] -= y;
x.y -= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] -= y;
x *= expr;
x *= ();
x *= x+y;
x *= x();
x[0] *= y;
x[0u32] *= y;
x.0 *= y;
x[1..2][0] *= y;
x[..2][0] *= y;
x[2..][0] *= y;
x[..][0] *= y;
x.0[0][..][0] *= y;
x.y *= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] *= y;
x /= expr;
x /= ();
x /= x+y;
x /= x();
x[0] /= y;
x[0u32] /= y;
x.0 /= y;
x[1..2][0] /= y;
x[..2][0] /= y;
x[2..][0] /= y;
x[..][0] /= y;
x.0[0][..][0] /= y;
x.y /= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] /= y;
x **= expr;
x **= ();
x **= x+y;
x **= x();
x[0] *= y;
x[0u32] *= y;
x.0 **= y;
x[1..2][0] **= y;
x[..2][0] **= y;
x[2..][0] **= y;
x[..][0] **= y;
x.0[0][..][0] **= y;
x.y **= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] **= y;

View File

@ -0,0 +1,32 @@
/*
namespace: ParseStatement
expectation: Fail
*/
x::y = y;
5 = y;
x + x = y;
-x = y;
!x = y;
a? x : x = y;
x as u32 = y;
[x, x, x] = y;
[x; 3] = y;
(x, x, x) = y;
x {x: y, y: z} = y;
x() = y;
x.y() = y;
🦀 = y;

View File

@ -0,0 +1,8 @@
/*
namespace: ParseStatement
expectation: Fail
*/
console.log(1);
console.test();

View File

@ -98,3 +98,8 @@ const (x, y): u32 = x();
let (x,y,) = ();
let x: [[u8; 2]; 2] = [[0,0], [0,0]];
let x: [u8; (2, 2)] = [[0,0], [0,0]];
let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;

View File

@ -53,6 +53,45 @@ let (,x,y) = ();
let (x,,y) = ();
let x: [u8; (2,,)] = [[0,0], [0,0]];
let x: const = expr;
const x: let = expr;
let x: mut = expr;
let
let x
let x:
let x = (a, y]);
let = 1u8;
let;
let x 1u8;
let x: u8;
let x: u8
let x: = 1;
let x: [u8] = 1;
let x: [u8;
let x: [u8; 1u8] = [1,
let dbg: u8 = ];
let 🦀: u8 = 0;
let (x) = ...;
let (x,) = ...;
let (x,) = ...;

View File

@ -0,0 +1,16 @@
/*
namespace: ParseStatement
expectation: Fail
*/
(];
[);
x\y;
(x,y|;
x[};
(x, y];

View File

@ -27,19 +27,28 @@ pub struct TestFailure {
#[derive(Debug)]
pub enum TestError {
Panicked {
test: String,
index: usize,
error: String,
},
UnexpectedOutput {
test: String,
index: usize,
expected: Value,
output: Value,
},
PassedAndShouldntHave {
test: String,
index: usize,
},
FailedAndShouldntHave {
test: String,
index: usize,
error: String,
},
UnexpectedError {
test: String,
index: usize,
expected: String,
output: String,
@ -50,30 +59,64 @@ pub enum TestError {
impl fmt::Display for TestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let format_test = |test: &str| -> String {
if test.len() > 50 {
String::new()
} else {
format!("\n\n{}\n\n", test)
}
};
match self {
TestError::Panicked { test, index, error } => {
write!(
f,
"test #{}: {}encountered a rust panic:\n{}",
index + 1,
format_test(test),
error
)
}
TestError::UnexpectedOutput {
test,
index,
expected,
output,
} => {
write!(
f,
"test #{} expected\n{}\ngot\n{}",
"test #{}: {}expected\n{}\ngot\n{}",
index + 1,
format_test(test),
serde_yaml::to_string(&expected).expect("serialization failed"),
serde_yaml::to_string(&output).expect("serialization failed")
)
}
TestError::PassedAndShouldntHave { index } => write!(f, "test #{} passed and shouldn't have", index + 1),
TestError::FailedAndShouldntHave { index, error } => {
write!(f, "test #{} failed and shouldn't have:\n{}", index + 1, error)
TestError::PassedAndShouldntHave { test, index } => {
write!(f, "test #{}: {}passed and shouldn't have", index + 1, format_test(test))
}
TestError::FailedAndShouldntHave { test, index, error } => {
write!(
f,
"test #{}: {}failed and shouldn't have:\n{}",
index + 1,
format_test(test),
error
)
}
TestError::UnexpectedError {
test,
expected,
output,
index,
} => {
write!(f, "test #{} expected error\n{}\ngot\n{}", index + 1, expected, output)
write!(
f,
"test #{}: {}expected error\n{}\ngot\n{}",
index + 1,
format_test(test),
expected,
output
)
}
TestError::MismatchedTestExpectationLength => write!(f, "invalid number of test expectations"),
TestError::MissingTestConfig => write!(f, "missing test config"),
@ -82,18 +125,25 @@ impl fmt::Display for TestError {
}
pub fn emit_errors(
output: Result<&Value, &str>,
test: &str,
output: &Result<Result<Value, String>, String>,
mode: &TestExpectationMode,
expected_output: Option<Value>,
test_index: usize,
) -> Option<TestError> {
match (output, mode) {
(Ok(output), TestExpectationMode::Pass) => {
(Err(e), _) => Some(TestError::Panicked {
test: test.to_string(),
index: test_index,
error: e.to_string(),
}),
(Ok(Ok(output)), TestExpectationMode::Pass) => {
// passed and should have
if let Some(expected_output) = expected_output.as_ref() {
if output != expected_output {
// invalid output
return Some(TestError::UnexpectedOutput {
test: test.to_string(),
index: test_index,
expected: expected_output.clone(),
output: output.clone(),
@ -102,18 +152,23 @@ pub fn emit_errors(
}
None
}
(Ok(_tokens), TestExpectationMode::Fail) => Some(TestError::PassedAndShouldntHave { index: test_index }),
(Err(err), TestExpectationMode::Pass) => Some(TestError::FailedAndShouldntHave {
(Ok(Ok(_tokens)), TestExpectationMode::Fail) => Some(TestError::PassedAndShouldntHave {
test: test.to_string(),
index: test_index,
}),
(Ok(Err(err)), TestExpectationMode::Pass) => Some(TestError::FailedAndShouldntHave {
test: test.to_string(),
error: err.to_string(),
index: test_index,
}),
(Err(err), TestExpectationMode::Fail) => {
(Ok(Err(err)), TestExpectationMode::Fail) => {
let expected_output: Option<String> =
expected_output.map(|x| serde_yaml::from_value(x).expect("test expectation deserialize failed"));
if let Some(expected_output) = expected_output.as_deref() {
if err != expected_output {
// invalid output
return Some(TestError::UnexpectedError {
test: test.to_string(),
expected: expected_output.to_string(),
output: err.to_string(),
index: test_index,

View File

@ -16,8 +16,12 @@
use serde_yaml::Value;
use std::{
any::Any,
collections::BTreeMap,
panic::{self, RefUnwindSafe, UnwindSafe},
path::{Path, PathBuf},
sync::{Arc, Mutex},
thread,
};
use crate::{error::*, fetch::find_tests, output::TestExpectation, test::*};
@ -36,7 +40,7 @@ pub struct Test {
pub config: BTreeMap<String, Value>,
}
pub trait Namespace {
pub trait Namespace: UnwindSafe + RefUnwindSafe {
fn parse_type(&self) -> ParseType;
fn run_test(&self, test: Test) -> Result<Value, String>;
@ -46,6 +50,30 @@ pub trait Runner {
fn resolve_namespace(&self, name: &str) -> Option<Box<dyn Namespace>>;
}
fn set_hook() -> Arc<Mutex<Option<String>>> {
let panic_buf = Arc::new(Mutex::new(None));
let thread_id = thread::current().id();
panic::set_hook({
let panic_buf = panic_buf.clone();
Box::new(move |e| {
if thread::current().id() == thread_id {
*panic_buf.lock().unwrap() = Some(e.to_string());
} else {
println!("{}", e)
}
})
});
panic_buf
}
fn take_hook(
output: Result<Result<Value, String>, Box<dyn Any + Send>>,
panic_buf: Arc<Mutex<Option<String>>>,
) -> Result<Result<Value, String>, String> {
let _ = panic::take_hook();
output.map_err(|_| panic_buf.lock().unwrap().take().expect("failed to get panic message"))
}
pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) {
std::env::remove_var("LEO_BACKTRACE"); // always remove backtrace so it doesn't clog output files
std::env::set_var("LEO_TESTFRAMEWORK", "true");
@ -149,24 +177,24 @@ pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) {
for (i, test) in tests.into_iter().enumerate() {
let expected_output = expected_output.as_mut().and_then(|x| x.next()).cloned();
println!("running test {} @ '{}'", test_name, path.to_str().unwrap());
let output = namespace.run_test(Test {
name: test_name.clone(),
content: test.clone(),
path: path.into(),
config: config.extra.clone(),
let panic_buf = set_hook();
let leo_output = panic::catch_unwind(|| {
namespace.run_test(Test {
name: test_name.clone(),
content: test.clone(),
path: path.into(),
config: config.extra.clone(),
})
});
if let Some(error) = emit_errors(
output.as_ref().map_err(|x| &**x),
&config.expectation,
expected_output,
i,
) {
let output = take_hook(leo_output, panic_buf);
if let Some(error) = emit_errors(&test, &output, &config.expectation, expected_output, i) {
fail_tests += 1;
errors.push(error);
} else {
pass_tests += 1;
new_outputs.push(
output
.unwrap()
.as_ref()
.map(|x| serde_yaml::to_value(x).expect("serialization failed"))
.unwrap_or_else(|e| Value::String(e.clone())),