Skip to content

Commit e2f2284

Browse files
committed
Add randomized unit test of nested_expr strings
1 parent e6a6040 commit e2f2284

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

tests/test_unit.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5485,6 +5485,111 @@ def testNestedExpressionDoesNotOverwriteParseActions(self):
54855485
expr = pp.nested_expr(content=content)
54865486
assert content.parseAction[0] is orig_pa
54875487

5488+
def testNestedExpressionRandom(self):
5489+
import random
5490+
5491+
word_chars = pp.alphanums
5492+
5493+
def get_random_character(_charset=word_chars + " "):
5494+
return random.choice(_charset)
5495+
5496+
def create_random_quoted_string():
5497+
quote_char = random.choice(('"', "'"))
5498+
yield quote_char
5499+
yield from (get_random_character() for _ in range(random.randint(0, 12)))
5500+
yield quote_char
5501+
5502+
def create_random_nested_expression():
5503+
yield "["
5504+
5505+
if random.random() < 0.25:
5506+
yield from create_random_quoted_string()
5507+
5508+
for _ in range(random.randint(0, 16)):
5509+
rnd = random.random()
5510+
if rnd < 0.25:
5511+
yield from create_random_quoted_string()
5512+
elif rnd < 0.3:
5513+
yield from create_random_nested_expression()
5514+
else:
5515+
yield from (get_random_character() for _ in range(random.randint(1, 4)))
5516+
5517+
if random.random() < 0.25:
5518+
yield from create_random_quoted_string()
5519+
5520+
yield "]"
5521+
5522+
num_reps=150
5523+
5524+
# simulate nested_expr
5525+
LBRACK, RBRACK = pp.Suppress.using_each("[]")
5526+
wd = pp.Word(word_chars)
5527+
qs = pp.quoted_string()
5528+
ls = pp.Forward()
5529+
ls <<= pp.Group(LBRACK + (qs | ls | wd)[...] + RBRACK)
5530+
5531+
def crack_nested_string(s) -> list:
5532+
return ls.parse_string(s, parse_all=True).as_list()
5533+
5534+
expr = pp.nested_expr('[', ']')
5535+
for _ in range(num_reps):
5536+
nested_str = ''.join(create_random_nested_expression())
5537+
# print(nested_str)
5538+
cracked_result = crack_nested_string(nested_str)
5539+
self.assertParseAndCheckList(
5540+
expr,
5541+
nested_str,
5542+
cracked_result,
5543+
f"Failed: {nested_str}, expected {cracked_result}",
5544+
verbose = False,
5545+
)
5546+
5547+
# test multi-character nesting delimiters
5548+
expr = pp.nested_expr('<<', '>>')
5549+
for _ in range(num_reps):
5550+
nested_str = ''.join(create_random_nested_expression())
5551+
# print(nested_str)
5552+
cracked_result = crack_nested_string(nested_str)
5553+
nested_str = nested_str.replace("[", "<<").replace("]", ">>")
5554+
self.assertParseAndCheckList(
5555+
expr,
5556+
nested_str,
5557+
cracked_result,
5558+
f"Failed: {nested_str}, expected {cracked_result}",
5559+
verbose = False,
5560+
)
5561+
5562+
# test with no ignore_expr (no quoted string handling)
5563+
expr = pp.nested_expr('[', ']', ignore_expr=None)
5564+
for _ in range(num_reps):
5565+
nested_str = ''.join(create_random_nested_expression())
5566+
nested_str = nested_str.replace('"', "").replace("'", "")
5567+
# print(nested_str)
5568+
cracked_result = crack_nested_string(nested_str)
5569+
self.assertParseAndCheckList(
5570+
expr,
5571+
nested_str,
5572+
cracked_result,
5573+
f"Failed: {nested_str}, expected {cracked_result}",
5574+
verbose = False,
5575+
)
5576+
5577+
# test multi-character nesting delimiters, with no ignore_expr
5578+
expr = pp.nested_expr('<<', '>>', ignore_expr=None)
5579+
for _ in range(num_reps):
5580+
nested_str = ''.join(create_random_nested_expression())
5581+
nested_str = nested_str.replace('"', "").replace("'", "")
5582+
# print(nested_str)
5583+
cracked_result = crack_nested_string(nested_str)
5584+
nested_str = nested_str.replace("[", "<<").replace("]", ">>")
5585+
self.assertParseAndCheckList(
5586+
expr,
5587+
nested_str,
5588+
cracked_result,
5589+
f"Failed: {nested_str}, expected {cracked_result}",
5590+
verbose=False,
5591+
)
5592+
54885593
def testWordMinMaxArgs(self):
54895594
parsers = [
54905595
"A" + pp.Word(pp.nums),

0 commit comments

Comments
 (0)