Adds integration tests that test whether a substring of a script can panic.

This commit is contained in:
Deukhoofd 2022-04-07 20:18:08 +02:00
parent b1d516b268
commit 69b5d76a9b
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
7 changed files with 124 additions and 10 deletions

View File

@ -8,6 +8,9 @@ use crate::parsing::parser::parse;
use crate::parsing::parser::parsed_statement::ParsedStatement;
use crate::span::Span;
fn ignore_error(_msg: Message, _: Span) {
}
fn panic_on_error(msg: Message, _: Span) {
std::panic::panic_any(msg.stringify());
}
@ -350,4 +353,18 @@ fn integration_add_function() {
}
}"#).unwrap();
assert_eq!(parsed_tree, expected_tree);
}
}
// A substring of a script should never panic, even though it might be completely invalid.
#[test]
fn integration_add_function_substring() {
let mut script = "int add(int a, int b) {
return a + b;
}".to_string();
for _ in 0..script.len() {
script.pop();
let lexed_tokens = lex(script.as_str(), &mut ignore_error);
let _parsed_tree = parse(lexed_tokens, &mut ignore_error);
}
}

View File

@ -8,6 +8,14 @@ fn main() {
let mod_file_path = Path::new("src/integration_tests/mod.rs");
let mut mod_file = File::create(mod_file_path).unwrap();
write!(
mod_file,
r#"////////////////////////////
// Automatically Generated//
////////////////////////////"#
)
.unwrap();
for path_opt in paths {
if let Err(..) = path_opt {
continue;
@ -45,6 +53,9 @@ use crate::parsing::parser::parse;
use crate::parsing::parser::parsed_statement::ParsedStatement;
use crate::span::Span;
fn ignore_error(_msg: Message, _: Span) {{
}}
fn panic_on_error(msg: Message, _: Span) {{
std::panic::panic_any(msg.stringify());
}}"#
@ -104,5 +115,25 @@ fn integration_{name}() {{
}
write!(testfile, "}}").unwrap();
write!(
testfile,
r##"
// A substring of a script should never panic, even though it might be completely invalid.
#[test]
fn integration_{name}_substring() {{
let mut script = "{script}".to_string();
for _ in 0..script.len() {{
script.pop();
let lexed_tokens = lex(script.as_str(), &mut ignore_error);
let _parsed_tree = parse(lexed_tokens, &mut ignore_error);
}}
}}
"##,
name = test_name,
script = script
)
.unwrap();
}
}

View File

@ -8,6 +8,9 @@ use crate::parsing::parser::parse;
use crate::parsing::parser::parsed_statement::ParsedStatement;
use crate::span::Span;
fn ignore_error(_msg: Message, _: Span) {
}
fn panic_on_error(msg: Message, _: Span) {
std::panic::panic_any(msg.stringify());
}
@ -90,4 +93,16 @@ fn integration_empty_class_declaration() {
}
}"#).unwrap();
assert_eq!(parsed_tree, expected_tree);
}
}
// A substring of a script should never panic, even though it might be completely invalid.
#[test]
fn integration_empty_class_declaration_substring() {
let mut script = "class Foo {}".to_string();
for _ in 0..script.len() {
script.pop();
let lexed_tokens = lex(script.as_str(), &mut ignore_error);
let _parsed_tree = parse(lexed_tokens, &mut ignore_error);
}
}

View File

@ -8,6 +8,9 @@ use crate::parsing::parser::parse;
use crate::parsing::parser::parsed_statement::ParsedStatement;
use crate::span::Span;
fn ignore_error(_msg: Message, _: Span) {
}
fn panic_on_error(msg: Message, _: Span) {
std::panic::panic_any(msg.stringify());
}
@ -436,4 +439,22 @@ fn integration_enum_definition() {
}
}"#).unwrap();
assert_eq!(parsed_tree, expected_tree);
}
}
// A substring of a script should never panic, even though it might be completely invalid.
#[test]
fn integration_enum_definition_substring() {
let mut script = "enum TestEnum : uint8 {
a,
b,
c,
d = 128,
e
}".to_string();
for _ in 0..script.len() {
script.pop();
let lexed_tokens = lex(script.as_str(), &mut ignore_error);
let _parsed_tree = parse(lexed_tokens, &mut ignore_error);
}
}

View File

@ -1,4 +1,6 @@
mod enum_definition;
////////////////////////////
// Automatically Generated//
////////////////////////////mod enum_definition;
mod multiple_inheritance_class;
mod empty_class_declaration;
mod add_function;

View File

@ -8,6 +8,9 @@ use crate::parsing::parser::parse;
use crate::parsing::parser::parsed_statement::ParsedStatement;
use crate::span::Span;
fn ignore_error(_msg: Message, _: Span) {
}
fn panic_on_error(msg: Message, _: Span) {
std::panic::panic_any(msg.stringify());
}
@ -170,4 +173,16 @@ fn integration_multiple_inheritance_class() {
}
}"#).unwrap();
assert_eq!(parsed_tree, expected_tree);
}
}
// A substring of a script should never panic, even though it might be completely invalid.
#[test]
fn integration_multiple_inheritance_class_substring() {
let mut script = "class Foo : Zom, Aar, Bar {}".to_string();
for _ in 0..script.len() {
script.pop();
let lexed_tokens = lex(script.as_str(), &mut ignore_error);
let _parsed_tree = parse(lexed_tokens, &mut ignore_error);
}
}

View File

@ -619,6 +619,10 @@ fn parse_class(
}
reader.consume(TokenType::CloseCurlyBracket, log);
if name.is_none() {
return Some(Box::new(ParsedStatement::Invalid));
}
Some(Box::new(ParsedStatement::ClassDeclaration {
modifiers,
name: name.unwrap(),
@ -670,6 +674,10 @@ fn parse_funcdef(
outer_reader.set_from_inner(&reader);
if identifier.is_none() || param_list.is_none() {
Some(Box::new(ParsedStatement::Invalid));
}
Some(Box::new(ParsedStatement::FuncDefDeclaration {
modifiers,
returns_reference,
@ -894,7 +902,10 @@ fn parse_paramlist(
break;
}
let param_type = parse_type(reader, log);
// FIXME: Deal with empty param_type
if param_type.is_none() {
// FIXME: Add logging
break;
}
let type_mod = parse_typemod(reader, log);
let identifier = parse_identifier(reader, log, true);
let mut default = None;
@ -1329,9 +1340,8 @@ fn parse_expr(
if let Some(..) = binary_operand {
let expr_term2 = parse_exprterm(reader, log);
if expr_term2.is_none() {
unimplemented!()
return Some(Box::new(ParsedStatement::Invalid));
}
// FIXME: deal with empty expr_term2
return Some(Box::new(ParsedStatement::BinaryExpr {
left: expr_term.unwrap(),
operator: binary_operand.unwrap(),
@ -1556,10 +1566,13 @@ fn parse_exprvalue(
}
fn parse_lambda(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
reader: &mut ParseReader,
log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// lambda ::= 'function' '(' [[type typemod] identifier {',' [type typemod] identifier}] ')' statblock;
if reader.peek().token_type != TokenType::FunctionKeyword {
return None;
}
unimplemented!();
}