gazprea-fuzzer-python/ast_generator/test/test_ast_generator.py

247 lines
8.3 KiB
Python
Raw Normal View History

2023-11-17 16:57:53 -07:00
import unittest
import xml
2023-11-17 16:57:53 -07:00
import xml.etree.ElementTree as ET
import xml.dom.minidom
import yaml
2023-11-17 16:57:53 -07:00
from ast_generator.ast_generator import *
from ast_generator.gazprea_ast_grammar import *
def reachable_return(block):
return True #TODO we actually need to check this
2023-11-17 16:57:53 -07:00
class TestGeneration(unittest.TestCase):
@classmethod
def setUpClass(cls):
with open("config.yaml", 'r') as stream:
props = yaml.safe_load(stream)
cls.ast_gen = AstGenerator(props)
2023-11-17 16:57:53 -07:00
def setUp(self):
self.ast_gen.current_nesting_depth = 0
self.ast_gen.current_control_flow_nesting_depth = 0
2023-11-17 16:57:53 -07:00
def test_generate_literal(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_literal('int')
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find(GAZ_LIT_TAG))
self.assertEqual("int", self.ast_gen.ast.find(GAZ_LIT_TAG).get("type"))
self.assertIsNotNone(self.ast_gen.ast.find(GAZ_LIT_TAG).get("value"))
self.assertIsNotNone(ET.tostring(self.ast_gen.ast, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
def test_generate_variable(self):
out: Variable = self.ast_gen.generate_variable('int')
self.assertEqual("int", out.xml.get("type"))
self.assertIsNotNone(out.xml.get("name"))
self.assertIsNotNone(out.xml.get("mut"))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(ET.tostring(out.xml, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
def test_generate_declaration(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_declaration()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("declaration"))
2023-11-17 16:57:53 -07:00
decl = self.ast_gen.ast.find("declaration")
self.assertIsNotNone(decl.find("variable"))
self.assertIsNotNone(decl.find("rhs"))
2023-11-17 16:57:53 -07:00
# print(ET.tostring(decl, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
def test_generate_assignment(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_declaration()
self.ast_gen.generate_assignment()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("assignment"))
2023-11-17 16:57:53 -07:00
decl = self.ast_gen.ast.find("assignment")
2023-11-17 16:57:53 -07:00
# print(ET.tostring(decl, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(decl.find("variable"))
self.assertIsNotNone(decl.find("rhs"))
2023-11-17 16:57:53 -07:00
def test_generate_bin_operation(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_binary('+', 'int')
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("operator"))
operator = self.ast_gen.ast.find("operator")
self.assertEqual('+', operator.get("op"))
self.assertEqual('int', operator.get("type"))
2023-11-17 16:57:53 -07:00
def test_generate_unary_operation(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_unary('-', 'int')
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("unary"))
operator = self.ast_gen.ast.find("unary")
self.assertEqual('-', operator.get("op"))
self.assertEqual('int', operator.get("type"))
2023-11-17 16:57:53 -07:00
def test_generate_stream(self):
for type in ["std_input", "std_output"]:
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_in_stream()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("stream"))
in_stream = self.ast_gen.ast.find("stream")
self.assertEqual("std_input", in_stream.get("type"))
2023-11-17 16:57:53 -07:00
lad = None
for child in in_stream.iter():
lad = child.attrib
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(lad)
2023-11-17 16:57:53 -07:00
def test_generate_block(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_block()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("block"))
2023-11-17 16:57:53 -07:00
elem = None
for child in self.ast_gen.ast.iter():
elem = child.attrib
self.assertIsNotNone(elem)
2023-11-17 16:57:53 -07:00
def test_generate_conditional(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_conditional()
2023-11-17 16:57:53 -07:00
print(ET.tostring(self.ast_gen.ast, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.current_ast_element.find("conditional"))
conditional = self.ast_gen.ast.find("conditional")
2023-11-17 16:57:53 -07:00
# print(ET.tostring(conditional, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(conditional.find("operator") or conditional.find("unary_operator") or conditional.find("literal"))
2023-11-17 16:57:53 -07:00
block = conditional.findall("block")
self.assertEqual(2, len(block))
2023-11-17 16:57:53 -07:00
def test_generate_loop(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_loop()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("loop"))
loop = self.ast_gen.ast.find("loop")
2023-11-17 16:57:53 -07:00
# print(ET.tostring(loop, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(loop.find("operator") or loop.find("unary_operator") or loop.find("literal"))
2023-11-17 16:57:53 -07:00
block = loop.findall("block")
self.assertEqual(1, len(block))
2023-11-17 16:57:53 -07:00
def test_generate_routine(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_routine()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("procedure") or self.ast_gen.ast.find("function"))
routine = self.ast_gen.ast.find("procedure") or self.ast_gen.ast.find("function")
2023-11-17 16:57:53 -07:00
print(ET.tostring(routine, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(routine.find("block"))
self.assertIsNotNone(routine.find("argument"))
2023-11-17 16:57:53 -07:00
def test_generate_function_ASSERT_RETURNS(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_routine(routine_type="function")
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("function"))
routine = self.ast_gen.ast.find("function")
2023-11-17 16:57:53 -07:00
print(ET.tostring(routine, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(routine.find("block"))
self.assertIsNotNone(routine.find("argument"))
2023-11-17 16:57:53 -07:00
block = routine.find("block")
print(ET.tostring(block, 'utf-8').decode('utf-8'))
rets = block.find("return")
print(rets)
self.assertLess(0, len(rets))
self.assertTrue(reachable_return(block))
2023-11-17 16:57:53 -07:00
def test_generate_main(self):
self.ast_gen.ast = ET.Element("block")
self.ast_gen.current_ast_element = self.ast_gen.ast
self.ast_gen.generate_main()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast.find("procedure"))
out = self.ast_gen.ast.find("procedure")
2023-11-17 16:57:53 -07:00
print(ET.tostring(out, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
self.assertEqual("main", out.get("name"))
self.assertEqual("int", out.get("return_type"))
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(out.find("block"))
block = out.find("block")
self.assertTrue(reachable_return(block))
2023-11-17 16:57:53 -07:00
self.assertIsNone(out.find("argument"))
2023-11-17 16:57:53 -07:00
def test_generate_ast(self):
self.ast_gen.generate_ast()
2023-11-17 16:57:53 -07:00
self.assertIsNotNone(self.ast_gen.ast)
2023-11-17 16:57:53 -07:00
print(ET.tostring(self.ast_gen.ast, 'utf-8').decode('utf-8'))
2023-11-17 16:57:53 -07:00
procedures = self.ast_gen.ast.findall("procedure")
self.assertLess(0, len(procedures))
2023-11-17 16:57:53 -07:00
main = False
for proc in procedures:
if proc.get("name") == "main":
main = True
self.assertTrue(main)
2023-11-17 16:57:53 -07:00
if __name__ == '__main__':
with open("config.yaml", 'r') as stream:
props = yaml.safe_load(stream)
ast_gen = AstGenerator(props)
for a in range(20):
ast_gen.generate_ast()
ast = ast_gen.ast
with open(f"xml/ast{a}.xml", 'x') as t:
dom = xml.dom.minidom.parseString(ET.tostring(ast).decode('utf-8'))
pretty: str = dom.toprettyxml()
repretty = ""
for line in pretty.split('\n'):
if line.startswith("<?xml"):
pass
else:
repretty += (line + '\n')
t.write(repretty)