1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::super::wat::WatParser;
use proptest::prelude::*;
proptest! {
fn parser_never_panics_on_arbitrary_input(
input in ".*"
) {
let mut parser = WatParser::new();
// Should not panic
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
parser.parse(&input)
}));
prop_assert!(result.is_ok());
}
fn valid_wat_modules_parse_successfully(
sections in prop::collection::vec(
prop_oneof![
Just("func"),
Just("memory"),
Just("table"),
Just("global"),
Just("export"),
Just("import"),
Just("type"),
],
0..10,
)
) {
// Build module from sections
let mut wat_content = "(module".to_string();
for (i, section) in sections.into_iter().enumerate() {
wat_content.push_str(&format!("\n ({} $item{})", section, i));
}
wat_content.push_str("\n)");
let mut parser = WatParser::new();
let result = parser.parse(&wat_content);
// Should successfully parse valid WAT modules
prop_assert!(result.is_ok(), "Failed to parse valid WAT: {}", wat_content);
}
fn invalid_wat_is_rejected(
invalid_type in 0usize..5
) {
let invalid_content = match invalid_type {
0 => "module without parens".to_string(),
1 => "(module (func".to_string(), // Unclosed
2 => "random text here".to_string(),
3 => "".to_string(),
_ => " \n\t ".to_string(), // Only whitespace
};
let mut parser = WatParser::new();
let result = parser.parse(&invalid_content);
// Should reject invalid WAT
prop_assert!(result.is_err(), "Accepted invalid WAT: {}", invalid_content);
}
fn parser_respects_size_limits(
repeat_count in 1usize..2000,
) {
let base_content = "(module (func $test))";
let mut parser = WatParser::new();
// Create large content by repeating
let large_content = base_content.repeat(repeat_count);
let result = parser.parse(&large_content);
if large_content.len() > 10 * 1024 * 1024 {
// Should reject files larger than 10MB
prop_assert!(result.is_err());
if let Err(e) = result {
prop_assert!(e.to_string().contains("too large"));
}
} else {
// Size is ok, check format
if large_content.trim_start().starts_with('(') {
prop_assert!(result.is_ok());
} else {
prop_assert!(result.is_err());
}
}
}
fn deeply_nested_structures_handled(
depth in 0u32..10,
count in 1usize..5,
) {
let mut parser = WatParser::new();
// Generate deeply nested module
let mut content = "(module".to_string();
for i in 0..count {
// Create a simple nested structure based on depth
let mut nested = String::new();
for _ in 0..depth {
nested.push('(');
}
nested.push_str(&format!("item{}", i));
for _ in 0..depth {
nested.push(')');
}
content.push_str(&format!("\n {}", nested));
}
content.push(')');
let result = parser.parse(&content);
// Should handle any depth without panicking
if content.len() <= 10 * 1024 * 1024 {
prop_assert!(result.is_ok());
}
}
fn whitespace_handling(
prefix_ws in "[ \t\n\r]*",
suffix_ws in "[ \t\n\r]*",
) {
let wat_content = "(module)";
let mut parser = WatParser::new();
// Test with various whitespace
let content_with_ws = format!("{}{}{}", prefix_ws, wat_content, suffix_ws);
let result = parser.parse(&content_with_ws);
// Should handle whitespace correctly
prop_assert!(result.is_ok());
}
fn unicode_handling(
unicode_chars in prop::collection::vec(any::<char>(), 0..20),
) {
let wat_base = "(module)";
let mut parser = WatParser::new();
// Create unicode string
let unicode_string: String = unicode_chars.into_iter().collect();
// Insert unicode string as a comment
let wat_with_unicode = format!("{} ;; {}", wat_base, unicode_string);
let result = parser.parse(&wat_with_unicode);
// Should handle unicode without panicking
if wat_with_unicode.len() <= 10 * 1024 * 1024 {
// Parser may accept or reject unicode, but shouldn't panic
let _ = result;
}
}
}
#[test]
fn empty_module_handling() {
let mut parser = WatParser::new();
let empty_modules = vec![
"(module)",
"(module )",
"(module\n)",
"(module\n\n)",
"( module )",
"(\nmodule\n)",
];
for module in empty_modules {
let result = parser.parse(module);
assert!(result.is_ok(), "Failed to parse empty module: {}", module);
}
}
// Property tests for additional trait implementations should be added
// when the following methods are implemented:
// - WasmAwareParser::parse_content (async)
// - WasmAwareParser::extract_wasm_metrics
// - WasmAwareParser::analyze_memory_patterns
// - WasmAwareParser::calculate_wasm_complexity
}