import unittest
import pytest
from rwl.hardening.parser_hardened import safe_json_parse, safe_xml_parse, safe_regex_search, ParserHardeningError
import xml.etree.ElementTree as ET

class TestParserHardening(unittest.TestCase):

    def test_safe_json_parse_valid_json(self):
        json_data = '{"name": "John Doe", "age": 30}'
        parsed_json = safe_json_parse(json_data)
        self.assertEqual(parsed_json["name"], "John Doe")
        self.assertEqual(parsed_json["age"], 30)

    def test_safe_json_parse_invalid_json(self):
        json_data = '{"name": "John Doe", "age": 30'  # Missing closing brace
        with self.assertRaises(ParserHardeningError):
            safe_json_parse(json_data)

    def test_safe_json_parse_max_length_exceeded(self):
        json_data = '{"long_string": "' + 'A' * 5000 + '"}'
        with self.assertRaises(ParserHardeningError):
            safe_json_parse(json_data, max_length=100)

    def test_safe_json_parse_max_nesting_exceeded(self):
        json_data = '{"level1": {"level2": {"level3": {"level4": {"level5": {"level6": {"level7": {"level8": {"level9": {"level10": {"level11": 1}}}}}}}}}}}}}'
        with self.assertRaises(ParserHardeningError):
            safe_json_parse(json_data, max_nesting=10)

    def test_safe_xml_parse_valid_xml(self):
        xml_data = '<root><element attribute="value">Text</element></root>'
        parsed_xml = safe_xml_parse(xml_data, allowed_tags=['root', 'element'], allowed_attributes=['attribute'])
        self.assertEqual(parsed_xml.tag, "root")
        self.assertEqual(parsed_xml[0].tag, "element")
        self.assertEqual(parsed_xml[0].get("attribute"), "value")
        self.assertEqual(parsed_xml[0].text, "Text")

    def test_safe_xml_parse_invalid_xml(self):
        xml_data = '<root><element attribute="value">Text</root>'  # Missing closing tag
        with self.assertRaises(ParserHardeningError):
            safe_xml_parse(xml_data)

    def test_safe_xml_parse_max_length_exceeded(self):
        xml_data = '<root><element attribute="value">' + 'A' * 5000 + '</element></root>'
        with self.assertRaises(ParserHardeningError):
            safe_xml_parse(xml_data, max_length=100)

    def test_safe_xml_parse_disallowed_tag(self):
        xml_data = '<root><evil_element>Text</evil_element></root>'
        with self.assertRaises(ParserHardeningError):
            safe_xml_parse(xml_data, allowed_tags=['root', 'element'])

    def test_safe_xml_parse_disallowed_attribute(self):
        xml_data = '<root><element evil_attribute="value">Text</element></root>'
        with self.assertRaises(ParserHardeningError):
            safe_xml_parse(xml_data, allowed_tags=['root', 'element'], allowed_attributes=['attribute'])

    def test_safe_regex_search_valid_regex(self):
        pattern = r"hello (\w+)"
        text = "hello world"
        match = safe_regex_search(pattern, text)
        self.assertIsNotNone(match)
        self.assertEqual(match.group(1), "world")

    def test_safe_regex_search_no_match(self):
        pattern = r"goodbye (\w+)"
        text = "hello world"
        match = safe_regex_search(pattern, text)
        self.assertIsNone(match)

    def test_safe_regex_search_invalid_regex(self):
        pattern = r"["  # Unbalanced square brackets
        text = "hello world"
        with self.assertRaises(ParserHardeningError):
            safe_regex_search(pattern, text)

    def test_safe_regex_search_max_length_exceeded(self):
        pattern = r"hello (\w+)"
        text = "hello " + "A" * 2000
        with self.assertRaises(ParserHardeningError):
            safe_regex_search(pattern, text, max_length=100)

    def test_safe_regex_search_too_many_groups(self):
        pattern = r"((a)(b)(c)(d)(e)(f)(g)(h)(i)(j))" # 11 capturing groups
        text = "abcdefghij"
        with self.assertRaises(ParserHardeningError):
            safe_regex_search(pattern, text, max_groups=10)


if __name__ == '__main__':
    unittest.main()