Skip to content

Commit

Permalink
Break sanitizer down to handler processors
Browse files Browse the repository at this point in the history
  • Loading branch information
tefra committed May 3, 2021
1 parent 79cd0a2 commit 8f0fd79
Show file tree
Hide file tree
Showing 21 changed files with 1,094 additions and 1,064 deletions.
147 changes: 147 additions & 0 deletions tests/codegen/handlers/test_attribute_default_value.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from unittest import mock

from xsdata.codegen.container import ClassContainer
from xsdata.codegen.handlers import AttributeDefaultValueHandler
from xsdata.models.enums import Namespace
from xsdata.utils.testing import AttrFactory
from xsdata.utils.testing import AttrTypeFactory
from xsdata.utils.testing import ClassFactory
from xsdata.utils.testing import FactoryTestCase


class AttributeDefaultValueHandlerTests(FactoryTestCase):
def setUp(self):
super().setUp()

container = ClassContainer()
self.processor = AttributeDefaultValueHandler(container=container)

def test_process_attribute_with_enumeration(self):
target = ClassFactory.create()
attr = AttrFactory.enumeration()
attr.restrictions.max_occurs = 2
attr.fixed = True

self.processor.process_attribute(target, attr)
self.assertTrue(attr.fixed)

def test_process_attribute_with_optional_field(self):
target = ClassFactory.create()
attr = AttrFactory.create(fixed=True, default=2)
attr.restrictions.min_occurs = 0
self.processor.process_attribute(target, attr)
self.assertFalse(attr.fixed)
self.assertIsNone(attr.default)

def test_process_attribute_with_xsi_type(self):
target = ClassFactory.create()
attr = AttrFactory.create(
fixed=True, default=2, name="type", namespace=Namespace.XSI.uri
)
self.processor.process_attribute(target, attr)
self.assertFalse(attr.fixed)
self.assertIsNone(attr.default)

def test_process_attribute_with_valid_case(self):
target = ClassFactory.create()
attr = AttrFactory.create(fixed=True, default=2)
self.processor.process_attribute(target, attr)
self.assertTrue(attr.fixed)
self.assertEqual(2, attr.default)

@mock.patch("xsdata.codegen.handlers.attribute_default_value.logger.warning")
@mock.patch.object(AttributeDefaultValueHandler, "find_enum")
def test_process_attribute_enum(self, mock_find_enum, mock_logger_warning):
enum_one = ClassFactory.enumeration(1, qname="{a}root")
enum_one.attrs[0].default = "1"
enum_one.attrs[0].name = "one"
enum_two = ClassFactory.enumeration(1, qname="inner")
enum_two.attrs[0].default = "2"
enum_two.attrs[0].name = "two"
enum_three = ClassFactory.enumeration(2, qname="missing_member")
enum_three.attrs[0].default = "4"
enum_three.attrs[0].name = "four"
enum_three.attrs[1].default = "5"
enum_three.attrs[1].name = "five"

mock_find_enum.side_effect = [
None,
enum_one,
None,
enum_two,
enum_three,
enum_three,
]

target = ClassFactory.create(
qname="target",
attrs=[
AttrFactory.create(
types=[
AttrTypeFactory.create(),
AttrTypeFactory.create(qname="foo"),
],
default="1",
),
AttrFactory.create(
types=[
AttrTypeFactory.create(),
AttrTypeFactory.create(qname="bar", forward=True),
],
default="2",
),
AttrFactory.create(default="3"),
AttrFactory.create(default=" 4 5"),
],
)

actual = []
for attr in target.attrs:
self.processor.process_attribute(target, attr)
actual.append(attr.default)

self.assertEqual(
[
"@enum@{a}root::one",
"@enum@inner::two",
None,
"@enum@missing_member::four@five",
],
actual,
)
mock_logger_warning.assert_called_once_with(
"No enumeration member matched %s.%s default value `%s`",
target.name,
target.attrs[2].local_name,
"3",
)

def test_find_enum(self):
native_type = AttrTypeFactory.create()
matching_external = AttrTypeFactory.create("foo")
missing_external = AttrTypeFactory.create("bar")
enumeration = ClassFactory.enumeration(1, qname="foo")
inner = ClassFactory.enumeration(1, qname="foobar")

target = ClassFactory.create(
attrs=[
AttrFactory.create(
types=[
native_type,
matching_external,
missing_external,
]
)
],
inner=[inner],
)
self.processor.container.extend([target, enumeration])

actual = self.processor.find_enum(native_type)
self.assertIsNone(actual)

actual = self.processor.find_enum(matching_external)
self.assertEqual(enumeration, actual)

actual = self.processor.find_enum(missing_external)
self.assertIsNone(actual)
52 changes: 52 additions & 0 deletions tests/codegen/handlers/test_attribute_name_conflict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from xsdata.codegen.handlers import AttributeNameConflictHandler
from xsdata.models.enums import Tag
from xsdata.utils.testing import AttrFactory
from xsdata.utils.testing import ClassFactory
from xsdata.utils.testing import FactoryTestCase


class AttributeNameConflictHandlerTests(FactoryTestCase):
def setUp(self):
super().setUp()

self.processor = AttributeNameConflictHandler()

def test_process(self):
attrs = [
AttrFactory.create(name="a", tag=Tag.ELEMENT),
AttrFactory.create(name="a", tag=Tag.ATTRIBUTE),
AttrFactory.create(name="b", tag=Tag.ATTRIBUTE),
AttrFactory.create(name="c", tag=Tag.ATTRIBUTE),
AttrFactory.create(name="c", tag=Tag.ELEMENT),
AttrFactory.create(name="d", tag=Tag.ELEMENT),
AttrFactory.create(name="d", tag=Tag.ELEMENT),
AttrFactory.create(name="e", tag=Tag.ELEMENT, namespace="b"),
AttrFactory.create(name="e", tag=Tag.ELEMENT),
AttrFactory.create(name="f", tag=Tag.ELEMENT),
AttrFactory.create(name="f", tag=Tag.ELEMENT, namespace="a"),
AttrFactory.create(name="gA", tag=Tag.ENUMERATION),
AttrFactory.create(name="g[A]", tag=Tag.ENUMERATION),
AttrFactory.create(name="g_a", tag=Tag.ENUMERATION),
AttrFactory.create(name="g_a_1", tag=Tag.ENUMERATION),
]
target = ClassFactory.create(attrs=attrs)

self.processor.process(target)
expected = [
"a",
"a_Attribute",
"b",
"c_Attribute",
"c",
"d_Element",
"d",
"b_e",
"e",
"f",
"a_f",
"gA",
"g[A]_2",
"g_a_3",
"g_a_1",
]
self.assertEqual(expected, [x.name for x in attrs])
112 changes: 112 additions & 0 deletions tests/codegen/handlers/test_attribute_restrictions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from xsdata.codegen.handlers import AttributeRestrictionsHandler
from xsdata.codegen.models import Class
from xsdata.codegen.models import Restrictions
from xsdata.models.enums import Tag
from xsdata.utils.testing import AttrFactory
from xsdata.utils.testing import ClassFactory
from xsdata.utils.testing import FactoryTestCase


class AttributeRestrictionsHandlerTests(FactoryTestCase):
def setUp(self):
super().setUp()

self.processor = AttributeRestrictionsHandler()

def test_reset_occurrences(self):
required = Restrictions(min_occurs=1, max_occurs=1)
attr = AttrFactory.attribute(restrictions=required.clone())
self.processor.reset_occurrences(attr)
self.assertIsNone(attr.restrictions.min_occurs)
self.assertIsNone(attr.restrictions.max_occurs)

tokens = Restrictions(required=True, tokens=True, min_occurs=1, max_occurs=1)
attr = AttrFactory.element(restrictions=tokens.clone())
self.processor.reset_occurrences(attr)
self.assertFalse(attr.restrictions.required)
self.assertIsNone(attr.restrictions.min_occurs)
self.assertIsNone(attr.restrictions.max_occurs)

attr = AttrFactory.element(restrictions=tokens.clone())
attr.restrictions.max_occurs = 2
self.processor.reset_occurrences(attr)
self.assertFalse(attr.restrictions.required)
self.assertIsNotNone(attr.restrictions.min_occurs)
self.assertIsNotNone(attr.restrictions.max_occurs)

multiple = Restrictions(min_occurs=0, max_occurs=2)
attr = AttrFactory.create(tag=Tag.EXTENSION, restrictions=multiple)
self.processor.reset_occurrences(attr)
self.assertTrue(attr.restrictions.required)
self.assertIsNone(attr.restrictions.min_occurs)
self.assertIsNone(attr.restrictions.max_occurs)

multiple = Restrictions(max_occurs=2, required=True)
attr = AttrFactory.element(restrictions=multiple, fixed=True)
self.processor.reset_occurrences(attr)
self.assertIsNone(attr.restrictions.required)
self.assertEqual(0, attr.restrictions.min_occurs)
self.assertFalse(attr.fixed)

attr = AttrFactory.element(restrictions=required.clone())
self.processor.reset_occurrences(attr)
self.assertTrue(attr.restrictions.required)
self.assertIsNone(attr.restrictions.min_occurs)
self.assertIsNone(attr.restrictions.max_occurs)

restrictions = Restrictions(required=True, min_occurs=0, max_occurs=1)
attr = AttrFactory.element(restrictions=restrictions, default="A", fixed=True)
self.processor.reset_occurrences(attr)
self.assertIsNone(attr.restrictions.required)
self.assertIsNone(attr.restrictions.min_occurs)
self.assertIsNone(attr.restrictions.max_occurs)
self.assertIsNone(attr.default)
self.assertFalse(attr.fixed)

attr = AttrFactory.element(restrictions=required.clone(), default="A")
self.processor.reset_occurrences(attr)
self.assertIsNone(attr.restrictions.required)

attr = AttrFactory.element(restrictions=required.clone(), fixed=True)
self.processor.reset_occurrences(attr)
self.assertIsNone(attr.restrictions.required)

attr = AttrFactory.element(restrictions=required.clone())
attr.restrictions.nillable = True
self.processor.reset_occurrences(attr)
self.assertIsNone(attr.restrictions.required)

def test_reset_sequential(self):
def len_sequential(target: Class):
return len([attr for attr in target.attrs if attr.restrictions.sequential])

restrictions = Restrictions(max_occurs=2, sequential=True)
target = ClassFactory.create(
attrs=[
AttrFactory.create(restrictions=restrictions.clone()),
AttrFactory.create(restrictions=restrictions.clone()),
]
)

attrs_clone = [attr.clone() for attr in target.attrs]

self.processor.reset_sequential(target, 0)
self.assertEqual(2, len_sequential(target))

target.attrs[0].restrictions.sequential = False
self.processor.reset_sequential(target, 0)
self.assertEqual(1, len_sequential(target))

self.processor.reset_sequential(target, 1)
self.assertEqual(0, len_sequential(target))

target.attrs = attrs_clone
target.attrs[1].restrictions.sequential = False
self.processor.reset_sequential(target, 0)
self.assertEqual(0, len_sequential(target))

target.attrs[0].restrictions.sequential = True
target.attrs[0].restrictions.max_occurs = 0
target.attrs[1].restrictions.sequential = True
self.processor.reset_sequential(target, 0)
self.assertEqual(1, len_sequential(target))
1 change: 0 additions & 1 deletion tests/codegen/handlers/test_attribute_sanitizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from xsdata.codegen.models import Status
from xsdata.models.enums import DataType
from xsdata.models.enums import Tag
from xsdata.utils import collections
from xsdata.utils.testing import AttrFactory
from xsdata.utils.testing import AttrTypeFactory
from xsdata.utils.testing import ClassFactory
Expand Down
Loading

0 comments on commit 8f0fd79

Please sign in to comment.