Skip to content

Commit 8c0a7fc

Browse files
chore: fix failing unit tests, #6627
1 parent 2924f6e commit 8c0a7fc

File tree

3 files changed

+73
-87
lines changed

3 files changed

+73
-87
lines changed

clarity-types/src/errors/ast.rs

Lines changed: 41 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::token::Token;
2424

2525
pub type ParseResult<T> = Result<T, ParseError>;
2626

27-
#[derive(PartialEq)]
27+
#[derive(Debug, PartialEq)]
2828
pub enum ParseErrors {
2929
// Cost errors
3030
CostOverflow,
@@ -149,9 +149,45 @@ impl fmt::Display for ParseError {
149149
}
150150
}
151151

152-
impl fmt::Display for ParseErrors {
153-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154-
let message = match &self {
152+
impl error::Error for ParseError {
153+
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
154+
None
155+
}
156+
}
157+
158+
impl From<ParseErrors> for ParseError {
159+
fn from(err: ParseErrors) -> Self {
160+
ParseError::new(err)
161+
}
162+
}
163+
164+
impl From<CostErrors> for ParseError {
165+
fn from(err: CostErrors) -> Self {
166+
match err {
167+
CostErrors::CostOverflow => ParseError::new(ParseErrors::CostOverflow),
168+
CostErrors::CostBalanceExceeded(a, b) => {
169+
ParseError::new(ParseErrors::CostBalanceExceeded(a, b))
170+
}
171+
CostErrors::MemoryBalanceExceeded(a, b) => {
172+
ParseError::new(ParseErrors::MemoryBalanceExceeded(a, b))
173+
}
174+
CostErrors::CostComputationFailed(s) => {
175+
ParseError::new(ParseErrors::CostComputationFailed(s))
176+
}
177+
CostErrors::CostContractLoadFailure => ParseError::new(
178+
ParseErrors::CostComputationFailed("Failed to load cost contract".into()),
179+
),
180+
CostErrors::InterpreterFailure | CostErrors::Expect(_) => {
181+
ParseError::new(ParseErrors::InterpreterFailure)
182+
}
183+
CostErrors::ExecutionTimeExpired => ParseError::new(ParseErrors::ExecutionTimeExpired),
184+
}
185+
}
186+
}
187+
188+
impl DiagnosableError for ParseErrors {
189+
fn message(&self) -> String {
190+
match &self {
155191
ParseErrors::CostOverflow => "Used up cost budget during the parse".into(),
156192
ParseErrors::CostBalanceExceeded(bal, used) => {
157193
format!("Used up cost budget during the parse: {bal} balance, {used} used")
@@ -259,89 +295,14 @@ impl fmt::Display for ParseErrors {
259295
}
260296
ParseErrors::TupleValueExpected => "expected value expression for tuple".into(),
261297
ParseErrors::IllegalClarityName(name) => format!("illegal clarity name, '{name}'"),
262-
ParseErrors::IllegalASCIIString(s) => {
263-
// Protect against console flooding and process hanging while running tests,
264-
// using a purely arbitrary max chars limit.
265-
#[cfg(any(test, feature = "testing"))]
266-
let s = shorten_string_for_test(s, 100);
267-
268-
format!("illegal ascii string \"{s}\"")
269-
}
298+
ParseErrors::IllegalASCIIString(s) => format!("illegal ascii string \"{s}\""),
270299
ParseErrors::ExpectedWhitespace => "expected whitespace before expression".into(),
271300
ParseErrors::NoteToMatchThis(token) => format!("to match this '{token}'"),
272301
ParseErrors::UnexpectedParserFailure => "unexpected failure while parsing".to_string(),
273302
ParseErrors::InterpreterFailure => "unexpected failure while parsing".to_string(),
274303
ParseErrors::ExecutionTimeExpired => "max execution time expired".to_string(),
275-
};
276-
write!(f, "{message}")
277-
}
278-
}
279-
280-
/// Test helper function to shorten big strings while running tests
281-
///
282-
/// This prevents both:
283-
/// - Console flooding with multi-megabyte output during test runs.
284-
/// - Potential test process blocking or hanging due to stdout buffering limits.
285-
///
286-
/// In case a the input `string` need to be shortned based on `max_chars`,
287-
/// the resulting string will be ellipsed showing the original character count.
288-
#[cfg(any(test, feature = "testing"))]
289-
fn shorten_string_for_test(string: &str, max_chars: usize) -> String {
290-
let char_count = string.chars().count();
291-
if char_count <= max_chars {
292-
string.into()
293-
} else {
294-
let shortened: String = string.chars().take(max_chars).collect();
295-
format!("{shortened}...[{char_count}]")
296-
}
297-
}
298-
299-
impl fmt::Debug for ParseErrors {
300-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
301-
fmt::Display::fmt(self, f)
302-
}
303-
}
304-
305-
impl error::Error for ParseError {
306-
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
307-
None
308-
}
309-
}
310-
311-
impl From<ParseErrors> for ParseError {
312-
fn from(err: ParseErrors) -> Self {
313-
ParseError::new(err)
314-
}
315-
}
316-
317-
impl From<CostErrors> for ParseError {
318-
fn from(err: CostErrors) -> Self {
319-
match err {
320-
CostErrors::CostOverflow => ParseError::new(ParseErrors::CostOverflow),
321-
CostErrors::CostBalanceExceeded(a, b) => {
322-
ParseError::new(ParseErrors::CostBalanceExceeded(a, b))
323-
}
324-
CostErrors::MemoryBalanceExceeded(a, b) => {
325-
ParseError::new(ParseErrors::MemoryBalanceExceeded(a, b))
326-
}
327-
CostErrors::CostComputationFailed(s) => {
328-
ParseError::new(ParseErrors::CostComputationFailed(s))
329-
}
330-
CostErrors::CostContractLoadFailure => ParseError::new(
331-
ParseErrors::CostComputationFailed("Failed to load cost contract".into()),
332-
),
333-
CostErrors::InterpreterFailure | CostErrors::Expect(_) => {
334-
ParseError::new(ParseErrors::InterpreterFailure)
335-
}
336-
CostErrors::ExecutionTimeExpired => ParseError::new(ParseErrors::ExecutionTimeExpired),
337304
}
338305
}
339-
}
340-
341-
impl DiagnosableError for ParseErrors {
342-
fn message(&self) -> String {
343-
format!("{self}")
344-
}
345306

346307
fn suggestion(&self) -> Option<String> {
347308
None

clarity/src/vm/ast/parser/v2/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,12 @@ impl<'a> Parser<'a> {
875875
match Value::string_ascii_from_bytes(val.clone().into_bytes()) {
876876
Ok(s) => PreSymbolicExpression::atom_value(s),
877877
Err(_) => {
878+
// Protect against console flooding and process hanging while running tests,
879+
// using a purely arbitrary max chars limit.
880+
// NOTE: A better place for this would be the enum itself, but then we need to write a custom Debug implementation
881+
#[cfg(any(test, feature = "testing"))]
882+
let val = ellipse_string_for_test(val, 128);
883+
878884
self.add_diagnostic(
879885
ParseErrors::IllegalASCIIString(val.clone()),
880886
token.span.clone(),
@@ -1110,6 +1116,25 @@ pub fn parse_collect_diagnostics(
11101116
(stmts, diagnostics, parser.success)
11111117
}
11121118

1119+
/// Test helper function to shorten big strings while running tests
1120+
///
1121+
/// This prevents both:
1122+
/// - Console flooding with multi-megabyte output during test runs.
1123+
/// - Potential test process blocking or hanging due to stdout buffering limits.
1124+
///
1125+
/// In case a the input `string` need to be shortned based on `max_chars`,
1126+
/// the resulting string will be ellipsed showing the original character count.
1127+
#[cfg(any(test, feature = "testing"))]
1128+
fn ellipse_string_for_test(string: &str, max_chars: usize) -> String {
1129+
let char_count = string.chars().count();
1130+
if char_count <= max_chars {
1131+
string.into()
1132+
} else {
1133+
let shortened: String = string.chars().take(max_chars).collect();
1134+
format!("{shortened}...[{char_count}]")
1135+
}
1136+
}
1137+
11131138
#[cfg(test)]
11141139
#[cfg(feature = "developer-mode")]
11151140
mod tests {

stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__parse_tests__illegal_ascii_string.snap

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ expression: result
99
transactions: [
1010
ExpectedTransactionOutput(
1111
tx: "SmartContract(name: my-contract-Epoch3_2-Clarity1, code_body: [..], clarity_version: Some(Clarity1))",
12-
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
12+
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
1313
return_type: Response(ResponseData(
1414
committed: false,
1515
data: Optional(OptionalData(
@@ -39,7 +39,7 @@ expression: result
3939
transactions: [
4040
ExpectedTransactionOutput(
4141
tx: "SmartContract(name: my-contract-Epoch3_2-Clarity2, code_body: [..], clarity_version: Some(Clarity2))",
42-
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
42+
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
4343
return_type: Response(ResponseData(
4444
committed: false,
4545
data: Optional(OptionalData(
@@ -69,7 +69,7 @@ expression: result
6969
transactions: [
7070
ExpectedTransactionOutput(
7171
tx: "SmartContract(name: my-contract-Epoch3_2-Clarity3, code_body: [..], clarity_version: Some(Clarity3))",
72-
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
72+
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
7373
return_type: Response(ResponseData(
7474
committed: false,
7575
data: Optional(OptionalData(
@@ -99,7 +99,7 @@ expression: result
9999
transactions: [
100100
ExpectedTransactionOutput(
101101
tx: "SmartContract(name: my-contract-Epoch3_3-Clarity1, code_body: [..], clarity_version: Some(Clarity1))",
102-
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
102+
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
103103
return_type: Response(ResponseData(
104104
committed: false,
105105
data: Optional(OptionalData(
@@ -129,7 +129,7 @@ expression: result
129129
transactions: [
130130
ExpectedTransactionOutput(
131131
tx: "SmartContract(name: my-contract-Epoch3_3-Clarity2, code_body: [..], clarity_version: Some(Clarity2))",
132-
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
132+
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
133133
return_type: Response(ResponseData(
134134
committed: false,
135135
data: Optional(OptionalData(
@@ -159,7 +159,7 @@ expression: result
159159
transactions: [
160160
ExpectedTransactionOutput(
161161
tx: "SmartContract(name: my-contract-Epoch3_3-Clarity3, code_body: [..], clarity_version: Some(Clarity3))",
162-
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
162+
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
163163
return_type: Response(ResponseData(
164164
committed: false,
165165
data: Optional(OptionalData(
@@ -189,7 +189,7 @@ expression: result
189189
transactions: [
190190
ExpectedTransactionOutput(
191191
tx: "SmartContract(name: my-contract-Epoch3_3-Clarity4, code_body: [..], clarity_version: Some(Clarity4))",
192-
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
192+
vm_error: "Some(illegal ascii string \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...[1048577]\") [NON-CONSENSUS BREAKING]",
193193
return_type: Response(ResponseData(
194194
committed: false,
195195
data: Optional(OptionalData(

0 commit comments

Comments
 (0)