Skip to content

Commit bbe2633

Browse files
authored
feat: Tidy the fuel functionality (#20)
1 parent 450a3f8 commit bbe2633

3 files changed

Lines changed: 77 additions & 33 deletions

File tree

crates/plotnik-lib/src/ast/parser/core.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::ast::syntax_kind::token_sets::ROOT_EXPR_FIRST;
1717
use crate::ast::syntax_kind::{SyntaxKind, TokenSet};
1818

1919
const DEFAULT_EXEC_FUEL: u32 = 1_000_000;
20-
const DEFAULT_RECURSION_FUEL: u32 = 512;
20+
const DEFAULT_RECURSION_FUEL: u32 = 4096;
2121

2222
/// Parse result containing the green tree and any errors.
2323
///

crates/plotnik-lib/src/ast/parser/tests/recovery/coverage.rs

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -320,17 +320,18 @@ fn capture_at_start_of_alternation() {
320320

321321
#[test]
322322
fn deeply_nested_trees_hit_recursion_limit() {
323-
// Test just over recursion limit (default is 512)
324-
let depth = 513;
323+
let depth = 128;
325324
let mut input = String::new();
326-
for _ in 0..depth {
325+
for _ in 0..depth + 1 {
327326
input.push_str("(a ");
328327
}
329328
for _ in 0..depth {
330329
input.push(')');
331330
}
332331

333-
let result = Query::builder(&input).build();
332+
let result = Query::builder(&input)
333+
.with_recursion_fuel(Some(depth))
334+
.build();
334335

335336
assert!(
336337
matches!(result, Err(crate::Error::RecursionLimitExceeded)),
@@ -341,17 +342,18 @@ fn deeply_nested_trees_hit_recursion_limit() {
341342

342343
#[test]
343344
fn deeply_nested_sequences_hit_recursion_limit() {
344-
// Test just over recursion limit (default is 512)
345-
let depth = 513;
345+
let depth = 128;
346346
let mut input = String::new();
347-
for _ in 0..depth {
347+
for _ in 0..depth + 1 {
348348
input.push_str("{(a) ");
349349
}
350350
for _ in 0..depth {
351351
input.push('}');
352352
}
353353

354-
let result = Query::builder(&input).build();
354+
let result = Query::builder(&input)
355+
.with_recursion_fuel(Some(depth))
356+
.build();
355357

356358
assert!(
357359
matches!(result, Err(crate::Error::RecursionLimitExceeded)),
@@ -362,17 +364,18 @@ fn deeply_nested_sequences_hit_recursion_limit() {
362364

363365
#[test]
364366
fn deeply_nested_alternations_hit_recursion_limit() {
365-
// Test just over recursion limit (default is 512)
366-
let depth = 513;
367+
let depth = 128;
367368
let mut input = String::new();
368-
for _ in 0..depth {
369+
for _ in 0..depth + 1 {
369370
input.push_str("[(a) ");
370371
}
371372
for _ in 0..depth {
372373
input.push(']');
373374
}
374375

375-
let result = Query::builder(&input).build();
376+
let result = Query::builder(&input)
377+
.with_recursion_fuel(Some(depth))
378+
.build();
376379

377380
assert!(
378381
matches!(result, Err(crate::Error::RecursionLimitExceeded)),
@@ -964,3 +967,64 @@ fn paren_close_inside_sequence() {
964967
| ^^^^ unnamed definition must be last in file; add a name: `Name = {(a)`
965968
"#);
966969
}
970+
971+
#[test]
972+
fn many_trees_exhaust_exec_fuel() {
973+
let count = 500;
974+
let mut input = String::new();
975+
for _ in 0..count {
976+
input.push_str("(a) ");
977+
}
978+
979+
let result = Query::builder(&input).with_exec_fuel(Some(100)).build();
980+
981+
assert!(
982+
matches!(result, Err(crate::Error::ExecFuelExhausted)),
983+
"expected ExecFuelExhausted error, got {:?}",
984+
result
985+
);
986+
}
987+
988+
#[test]
989+
fn many_branches_exhaust_exec_fuel() {
990+
let count = 500;
991+
let mut input = String::new();
992+
input.push('[');
993+
for i in 0..count {
994+
if i > 0 {
995+
input.push(' ');
996+
}
997+
input.push_str("(a)");
998+
}
999+
input.push(']');
1000+
1001+
let result = Query::builder(&input).with_exec_fuel(Some(100)).build();
1002+
1003+
assert!(
1004+
matches!(result, Err(crate::Error::ExecFuelExhausted)),
1005+
"expected ExecFuelExhausted error, got {:?}",
1006+
result
1007+
);
1008+
}
1009+
1010+
#[test]
1011+
fn many_fields_exhaust_exec_fuel() {
1012+
let count = 500;
1013+
let mut input = String::new();
1014+
input.push('(');
1015+
for i in 0..count {
1016+
if i > 0 {
1017+
input.push(' ');
1018+
}
1019+
input.push_str("a: (b)");
1020+
}
1021+
input.push(')');
1022+
1023+
let result = Query::builder(&input).with_exec_fuel(Some(100)).build();
1024+
1025+
assert!(
1026+
matches!(result, Err(crate::Error::ExecFuelExhausted)),
1027+
"expected ExecFuelExhausted error, got {:?}",
1028+
result
1029+
);
1030+
}

crates/plotnik-lib/src/ast/parser/tests/recovery/incomplete.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -208,23 +208,3 @@ fn bare_missing_keyword() {
208208
| ^^^^^^^ ERROR and MISSING must be inside parentheses: (ERROR) or (MISSING ...)
209209
"#);
210210
}
211-
212-
#[test]
213-
fn deep_nesting_within_limit() {
214-
let depth = 100;
215-
let mut input = String::new();
216-
for _ in 0..depth {
217-
input.push_str("(a ");
218-
}
219-
for _ in 0..depth {
220-
input.push(')');
221-
}
222-
223-
let result = crate::ast::parser::parse(&input).unwrap();
224-
assert!(
225-
result.is_valid(),
226-
"expected no errors for depth {}, got: {:?}",
227-
depth,
228-
result.errors()
229-
);
230-
}

0 commit comments

Comments
 (0)