##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
""" GenericSetup.utils unit tests

$Id: test_utils.py 90525 2008-08-28 08:54:09Z jens $
"""

import unittest
import Testing

from Testing.ZopeTestCase import ZopeTestCase
from Testing.ZopeTestCase import installProduct

installProduct('GenericSetup')

_EMPTY_PROPERTY_EXPORT = """\
<?xml version="1.0"?>
<dummy>
 <property name="foo_boolean" type="boolean">False</property>
 <property name="foo_date" type="date">1970/01/01</property>
 <property name="foo_float" type="float">0.0</property>
 <property name="foo_int" type="int">0</property>
 <property name="foo_lines" type="lines"/>
 <property name="foo_long" type="long">0</property>
 <property name="foo_string" type="string"></property>
 <property name="foo_text" type="text"></property>
 <property name="foo_tokens" type="tokens"/>
 <property name="foo_selection" select_variable="foobarbaz"
    type="selection"></property>
 <property name="foo_mselection" select_variable="foobarbaz"
    type="multiple selection"/>
 <property name="foo_boolean0" type="boolean">False</property>
 <property name="foo_int_nodel">0</property>
 <property name="foo_float_nodel">0.0</property>
 <property name="foo_boolean_nodel">False</property>
</dummy>
"""

_NORMAL_PROPERTY_EXPORT = u"""\
<?xml version="1.0"?>
<dummy>
 <property name="foo_boolean" type="boolean">True</property>
 <property name="foo_date" type="date">2000/01/01</property>
 <property name="foo_float" type="float">1.1</property>
 <property name="foo_int" type="int">1</property>
 <property name="foo_lines" type="lines">
  <element value="Foo"/>
  <element value="Lines"/>
  <element value="\xfcbrigens"/>
 </property>
 <property name="foo_long" type="long">1</property>
 <property name="foo_string" type="string">Foo String</property>
 <property name="foo_text" type="text">Foo
  Text</property>
 <property name="foo_tokens" type="tokens">
  <element value="Foo"/>
  <element value="Tokens"/>
 </property>
 <property name="foo_selection" select_variable="foobarbaz"
    type="selection">Foo</property>
 <property name="foo_mselection" select_variable="foobarbaz"
    type="multiple selection">
  <element value="Foo"/>
  <element value="Baz"/>
 </property>
 <property name="foo_boolean0" type="boolean">False</property>
 <property name="foo_int_nodel">1789</property>
 <property name="foo_float_nodel">3.1415</property>
 <property name="foo_boolean_nodel">True</property>
</dummy>
""".encode('utf-8')

_FIXED_PROPERTY_EXPORT = u"""\
<?xml version="1.0"?>
<dummy>
 <property name="foo_boolean">True</property>
 <property name="foo_date">2000/01/01</property>
 <property name="foo_float">1.1</property>
 <property name="foo_int">1</property>
 <property name="foo_lines">
  <element value="Foo"/>
  <element value="Lines"/>
 <element value="\xfcbrigens"/>
 </property>
 <property name="foo_long">1</property>
 <property name="foo_string">Foo String</property>
 <property name="foo_text">Foo
  Text</property>
 <property name="foo_tokens">
  <element value="Foo"/>
  <element value="Tokens"/></property>
 <property name="foo_selection" type="selection"
    select_variable="foobarbaz">Foo</property>
 <property name="foo_mselection">
  <element value="Foo"/>
  <element value="Baz"/>
 </property>
 <property name="foo_boolean0">False</property>
 <property name="foo_int_nodel">1789</property>
 <property name="foo_float_nodel">3.1415</property>
 <property name="foo_boolean_nodel">True</property>
</dummy>
""".encode('utf-8')

_SPECIAL_IMPORT = """\
<?xml version="1.0"?>
<dummy>
 <!-- ignore comment, import 0 as False -->
 <property name="foo_boolean0" type="boolean">0</property>
</dummy>
"""

_I18N_IMPORT = """\
<?xml version="1.0"?>
<dummy xmlns:i18n="http://xml.zope.org/namespaces/i18n"
   i18n:domain="dummy_domain">
 <property name="foo_string" i18n:translate="">Foo String</property>
</dummy>
"""

_NOPURGE_IMPORT = """\
<?xml version="1.0"?>
<dummy>
 <property name="lines1">
  <element value="Foo"/>
  <element value="Bar"/>
 </property>
 <property name="lines2" purge="True">
  <element value="Foo"/>
  <element value="Bar"/>
 </property>
 <property name="lines3" purge="False">
  <element value="Foo"/>
  <element value="Bar"/>
 </property>
</dummy>
"""
_REMOVE_ELEMENT_IMPORT = """\
<?xml version="1.0"?>
<dummy>
 <property name="lines1" purge="False">
   <element value="Foo" remove="True" />
   <element value="Bar" />
  </property>
</dummy>
"""

_NORMAL_MARKER_EXPORT = """\
<?xml version="1.0"?>
<dummy>
 <marker name="Products.GenericSetup.testing.IDummyMarker"/>
</dummy>
"""

_ADD_IMPORT = """\
<?xml version="1.0"?>
<dummy>
 <object name="history" meta_type="Generic Setup Tool"/>
</dummy>
"""
_REMOVE_IMPORT = """\
<?xml version="1.0"?>
<dummy>
 <object name="history" remove="True"/>
</dummy>
"""

def _getDocumentElement(text):
    from xml.dom.minidom import parseString
    return parseString(text).documentElement


def _testFunc( *args, **kw ):

    """ This is a test.

    This is only a test.
    """

_TEST_FUNC_NAME = 'Products.GenericSetup.tests.test_utils._testFunc'

class Whatever:
    pass

_WHATEVER_NAME = 'Products.GenericSetup.tests.test_utils.Whatever'

whatever_inst = Whatever()
whatever_inst.__name__ = 'whatever_inst'

_WHATEVER_INST_NAME = 'Products.GenericSetup.tests.test_utils.whatever_inst'

class UtilsTests( unittest.TestCase ):

    def test__getDottedName_simple( self ):

        from Products.GenericSetup.utils import _getDottedName

        self.assertEqual( _getDottedName( _testFunc ), _TEST_FUNC_NAME )

    def test__getDottedName_string( self ):

        from Products.GenericSetup.utils import _getDottedName

        self.assertEqual( _getDottedName( _TEST_FUNC_NAME ), _TEST_FUNC_NAME )

    def test__getDottedName_unicode( self ):

        from Products.GenericSetup.utils import _getDottedName

        dotted = u'%s' % _TEST_FUNC_NAME
        self.assertEqual( _getDottedName( dotted ), _TEST_FUNC_NAME )
        self.assertEqual( type( _getDottedName( dotted ) ), str )

    def test__getDottedName_class( self ):

        from Products.GenericSetup.utils import _getDottedName

        self.assertEqual( _getDottedName( Whatever ), _WHATEVER_NAME )

    def test__getDottedName_inst( self ):

        from Products.GenericSetup.utils import _getDottedName

        self.assertEqual( _getDottedName( whatever_inst )
                        , _WHATEVER_INST_NAME )

    def test__getDottedName_noname( self ):

        from Products.GenericSetup.utils import _getDottedName

        class Doh:
            pass

        doh = Doh()
        self.assertRaises( ValueError, _getDottedName, doh )


class PropertyManagerHelpersTests(unittest.TestCase):

    def _getTargetClass(self):
        from Products.GenericSetup.utils import PropertyManagerHelpers

        return PropertyManagerHelpers

    def _makeOne(self, context=None, environ=None):
        from Products.GenericSetup.utils import NodeAdapterBase
        from Products.GenericSetup.testing import DummySetupEnviron

        class Foo(self._getTargetClass(), NodeAdapterBase):
            pass

        if context is None:
            context = self._makeContext()

        if environ is None:
            environ = DummySetupEnviron()

        return Foo(context, environ)

    def _makeContext(self):
        from OFS.PropertyManager import PropertyManager
        obj = PropertyManager('obj')
        obj.foobarbaz = ('Foo', 'Bar', 'Baz')
        obj._properties = ()
        obj.manage_addProperty('foo_boolean', '', 'boolean')
        obj.manage_addProperty('foo_date', '1970/01/01', 'date')
        obj.manage_addProperty('foo_float', '0', 'float')
        obj.manage_addProperty('foo_int', '0', 'int')
        obj.manage_addProperty('foo_lines', '', 'lines')
        obj.manage_addProperty('foo_long', '0', 'long')
        obj.manage_addProperty('foo_string', '', 'string')
        obj.manage_addProperty('foo_text', '', 'text')
        obj.manage_addProperty('foo_tokens', '', 'tokens')
        obj.manage_addProperty('foo_selection', 'foobarbaz', 'selection')
        obj.manage_addProperty('foo_mselection', 'foobarbaz',
                               'multiple selection')
        obj.manage_addProperty('foo_boolean0', '', 'boolean')
        obj.manage_addProperty('foo_ro', '', 'string')
        obj._properties[-1]['mode'] = '' # Read-only, not exported or purged
        obj.manage_addProperty('foo_int_nodel', 0, 'int')
        obj._properties[-1]['mode'] = 'w' # Not deletable
        obj.manage_addProperty('foo_float_nodel', 0, 'float')
        obj._properties[-1]['mode'] = 'w' # Not deletable
        obj.manage_addProperty('foo_boolean_nodel', '', 'boolean')
        obj._properties[-1]['mode'] = 'w' # Not deletable
        return obj

    def _getReal(self, obj):
        return obj

    def _populate(self, obj):
        obj._updateProperty('foo_boolean', 'True')
        obj._updateProperty('foo_date', '2000/01/01')
        obj._updateProperty('foo_float', '1.1')
        obj._updateProperty('foo_int', '1')
        obj._updateProperty('foo_lines', 
                u'Foo\nLines\n\xfcbrigens'.encode('utf-8'))
        obj._updateProperty('foo_long', '1')
        obj._updateProperty('foo_string', 'Foo String')
        obj._updateProperty('foo_text', 'Foo\nText')
        obj._updateProperty( 'foo_tokens', ('Foo', 'Tokens') )
        obj._updateProperty('foo_selection', 'Foo')
        obj._updateProperty( 'foo_mselection', ('Foo', 'Baz') )
        obj.foo_boolean0 = 0
        obj._updateProperty('foo_ro', 'RO')
        obj._updateProperty('foo_int_nodel', '1789')
        obj._updateProperty('foo_float_nodel', '3.1415')
        obj._updateProperty('foo_boolean_nodel', 'True')

    def test__extractProperties_empty(self):
        from Products.GenericSetup.utils import PrettyDocument
        helpers = self._makeOne()
        doc = helpers._doc = PrettyDocument()
        node = doc.createElement('dummy')
        node.appendChild(helpers._extractProperties())
        doc.appendChild(node)

        self.assertEqual(doc.toprettyxml(' '), _EMPTY_PROPERTY_EXPORT)

    def test__extractProperties_normal(self):
        from Products.GenericSetup.utils import PrettyDocument
        helpers = self._makeOne()
        obj = self._getReal(helpers.context)
        self._populate(obj)
        doc = helpers._doc = PrettyDocument()
        node = doc.createElement('dummy')

        # The extraction process wants to decode text properties
        # to unicode using the default ZPublisher encoding, which
        # defaults to iso-8859-15. We force UTF-8 here because we 
        # forced our properties to be UTF-8 encoded.
        helpers._encoding = 'utf-8'
        node.appendChild(helpers._extractProperties())
        doc.appendChild(node)

        self.assertEqual(doc.toprettyxml(' '), _NORMAL_PROPERTY_EXPORT)

    def test__purgeProperties(self):
        helpers = self._makeOne()
        obj = self._getReal(helpers.context)
        self._populate(obj)
        helpers._purgeProperties()

        self.assertEqual(getattr(obj, 'foo_boolean', None), None)
        self.assertEqual(getattr(obj, 'foo_date', None), None)
        self.assertEqual(getattr(obj, 'foo_float', None), None)
        self.assertEqual(getattr(obj, 'foo_int', None), None)
        self.assertEqual(getattr(obj, 'foo_lines', None), None)
        self.assertEqual(getattr(obj, 'foo_long', None), None)
        self.assertEqual(getattr(obj, 'foo_string', None), None)
        self.assertEqual(getattr(obj, 'foo_text', None), None)
        self.assertEqual(getattr(obj, 'foo_tokens', None), None)
        self.assertEqual(getattr(obj, 'foo_selection', None), None)
        self.assertEqual(getattr(obj, 'foo_mselection', None), None)
        self.assertEqual(getattr(obj, 'foo_boolean0', None), None)
        self.assertEqual(getattr(obj, 'foo_ro', None), 'RO')

    def test__initProperties_normal(self):
        from Products.GenericSetup.utils import PrettyDocument
        helpers = self._makeOne()
        obj = self._getReal(helpers.context)
        node = _getDocumentElement(_NORMAL_PROPERTY_EXPORT)
        helpers._initProperties(node)
        self.assertEqual(type(obj.foo_int), int)
        self.assertEqual(type(obj.foo_string), str)
        self.assertEqual(type(obj.foo_tokens), tuple)
        self.assertEqual(type(obj.foo_tokens[0]), str)

        doc = helpers._doc = PrettyDocument()
        node = doc.createElement('dummy')
        node.appendChild(helpers._extractProperties())
        doc.appendChild(node)

        self.assertEqual(doc.toprettyxml(' '), _NORMAL_PROPERTY_EXPORT)

    def test__initProperties_fixed(self):
        from Products.GenericSetup.utils import PrettyDocument
        helpers = self._makeOne()
        node = _getDocumentElement(_FIXED_PROPERTY_EXPORT)
        helpers._initProperties(node)

        doc = helpers._doc = PrettyDocument()
        node = doc.createElement('dummy')
        node.appendChild(helpers._extractProperties())
        doc.appendChild(node)

        self.assertEqual(doc.toprettyxml(' '), _NORMAL_PROPERTY_EXPORT)

    def test__initProperties_special(self):
        from Products.GenericSetup.utils import PrettyDocument
        helpers = self._makeOne()
        node = _getDocumentElement(_SPECIAL_IMPORT)
        helpers._initProperties(node)

        doc = helpers._doc = PrettyDocument()
        node = doc.createElement('dummy')
        node.appendChild(helpers._extractProperties())
        doc.appendChild(node)

        self.assertEqual(doc.toprettyxml(' '), _EMPTY_PROPERTY_EXPORT)

    def test__initProperties_i18n(self):
        helpers = self._makeOne()
        helpers.context.manage_addProperty('i18n_domain', '', 'string')
        node = _getDocumentElement(_I18N_IMPORT)
        helpers._initProperties(node)

        self.assertEqual(helpers.context.getProperty('i18n_domain'),
                        'dummy_domain')

    def test__initProperties_nopurge_base(self):
        helpers = self._makeOne()
        node = _getDocumentElement(_NOPURGE_IMPORT)
        helpers.environ._should_purge = True # base profile
        obj = helpers.context
        obj._properties = ()
        obj.manage_addProperty('lines1', ('Foo', 'Gee'), 'lines')
        obj.manage_addProperty('lines2', ('Foo', 'Gee'), 'lines')
        obj.manage_addProperty('lines3', ('Foo', 'Gee'), 'lines')
        helpers._initProperties(node)

        self.assertEquals(obj.getProperty('lines1'), ('Foo', 'Bar'))
        self.assertEquals(obj.getProperty('lines2'), ('Foo', 'Bar'))
        self.assertEquals(obj.getProperty('lines3'), ('Gee', 'Foo', 'Bar'))

    def test__initProperties_nopurge_extension(self):
        helpers = self._makeOne()
        node = _getDocumentElement(_NOPURGE_IMPORT)
        helpers.environ._should_purge = False # extension profile
        obj = helpers.context
        obj._properties = ()
        obj.manage_addProperty('lines1', ('Foo', 'Gee'), 'lines')
        obj.manage_addProperty('lines2', ('Foo', 'Gee'), 'lines')
        obj.manage_addProperty('lines3', ('Foo', 'Gee'), 'lines')
        helpers._initProperties(node)

        self.assertEquals(obj.getProperty('lines1'), ('Foo', 'Bar'))
        self.assertEquals(obj.getProperty('lines2'), ('Foo', 'Bar'))
        self.assertEquals(obj.getProperty('lines3'), ('Gee', 'Foo', 'Bar'))

    def test_initProperties_remove_elements(self):
        helpers = self._makeOne()
        node = _getDocumentElement(_REMOVE_ELEMENT_IMPORT)
        helpers.environ._should_purge = False # extension profile
        obj = helpers.context
        obj._properties = ()
        obj.manage_addProperty('lines1', ('Foo', 'Gee'), 'lines')
        helpers._initProperties(node)

        self.assertEquals(obj.getProperty('lines1'), ('Gee', 'Bar'))

class PropertyManagerHelpersNonPMContextTests(PropertyManagerHelpersTests):

    def _makeOne(self, context=None, environ=None):
        from Products.GenericSetup.utils import NodeAdapterBase
        from Products.GenericSetup.testing import DummySetupEnviron

        class Foo(self._getTargetClass(), NodeAdapterBase):
            _PROPERTIES = (
                {'id': 'foo_boolean', 'type': 'boolean', 'mode': 'wd'},
                {'id': 'foo_date', 'type': 'date', 'mode': 'wd'},
                {'id': 'foo_float', 'type': 'float', 'mode': 'wd'},
                {'id': 'foo_int', 'type': 'int', 'mode': 'wd'},
                {'id': 'foo_lines', 'type': 'lines', 'mode': 'wd'},
                {'id': 'foo_long', 'type': 'long', 'mode': 'wd'},
                {'id': 'foo_string', 'type': 'string', 'mode': 'wd'},
                {'id': 'foo_text', 'type': 'text', 'mode': 'wd'},
                {'id': 'foo_tokens', 'type': 'tokens', 'mode': 'wd'},
                {'id': 'foo_selection', 'type': 'selection',
                       'select_variable': 'foobarbaz', 'mode': 'wd'},
                {'id': 'foo_mselection', 'type': 'multiple selection',
                       'select_variable': 'foobarbaz', 'mode': 'wd'},
                {'id': 'foo_boolean0', 'type': 'boolean', 'mode': 'wd'},
                {'id': 'foo_ro', 'type': 'string', 'mode': ''},
                {'id': 'foo_int_nodel', 'type': 'int', 'mode': 'w'},
                {'id': 'foo_float_nodel', 'type': 'float', 'mode': 'w'},
                {'id': 'foo_boolean_nodel', 'type': 'boolean', 'mode': 'w'},
            )

        if context is None:
            context = self._makeContext()

        if environ is None:
            environ = DummySetupEnviron()

        return Foo(context, environ)

    def _makeContext(self):
        from DateTime.DateTime import DateTime
        class NonPropertyManager:
            pass
        obj = NonPropertyManager()
        obj.foobarbaz = ('Foo', 'Bar', 'Baz')
        obj.foo_boolean = False
        obj.foo_date = DateTime('1970/01/01')
        obj.foo_float = 0.0
        obj.foo_int = 0
        obj.foo_lines = []
        obj.foo_long = 0
        obj.foo_string = ''
        obj.foo_text = ''
        obj.foo_tokens = ()
        obj.foo_selection = ''
        obj.foo_mselection = ()
        obj.foo_boolean0 = 0
        obj.foo_ro = ''
        obj.foo_int_nodel = 0
        obj.foo_float_nodel = 0.0
        obj.foo_boolean_nodel = False
        return obj

    def _getReal(self, obj):
        return obj._real

    def _populate(self, obj):
        from DateTime.DateTime import DateTime
        obj.foo_boolean = True
        obj.foo_date = DateTime('2000/01/01')
        obj.foo_float = 1.1
        obj.foo_int = 1
        obj.foo_lines = ['Foo', 'Lines', u'\xfcbrigens'.encode('utf-8')]
        obj.foo_long = 1
        obj.foo_string = 'Foo String'
        obj.foo_text = 'Foo\nText'
        obj.foo_tokens = ('Foo', 'Tokens')
        obj.foo_selection = 'Foo'
        obj.foo_mselection = ('Foo', 'Baz')
        obj.foo_boolean0 = 0
        obj.foo_ro = 'RO'
        obj.foo_int_nodel = 1789
        obj.foo_float_nodel = 3.1415
        obj.foo_boolean_nodel = True


class MarkerInterfaceHelpersTests(unittest.TestCase):

    def _getTargetClass(self):
        from Products.GenericSetup.utils import MarkerInterfaceHelpers

        return MarkerInterfaceHelpers

    def _makeOne(self, context=None, environ=None):
        from Products.GenericSetup.utils import NodeAdapterBase
        from Products.GenericSetup.testing import DummySetupEnviron

        class Foo(self._getTargetClass(), NodeAdapterBase):
            pass

        if context is None:
            context = self._makeContext()

        if environ is None:
            environ = DummySetupEnviron()

        return Foo(context, environ)

    def _makeContext(self):
        from OFS.SimpleItem import Item
        return Item('obj')

    def _populate(self, obj):
        from zope.interface import directlyProvides
        from Products.GenericSetup.testing import IDummyMarker
        directlyProvides(obj, IDummyMarker)

    def setUp(self):
        from zope.component import provideAdapter
        from zope.component.interface import provideInterface
        from OFS.interfaces import IItem
        from Products.Five.utilities.marker import MarkerInterfacesAdapter
        from Products.GenericSetup.testing import IDummyMarker
        provideAdapter(MarkerInterfacesAdapter, (IItem,))
        provideInterface('', IDummyMarker)

    def tearDown(self):
        from zope.testing.cleanup import cleanUp
        cleanUp()

    def test__extractMarkers(self):
        from Products.GenericSetup.utils import PrettyDocument
        helpers = self._makeOne()
        self._populate(helpers.context)
        doc = helpers._doc = PrettyDocument()
        node = doc.createElement('dummy')
        node.appendChild(helpers._extractMarkers())
        doc.appendChild(node)

        self.assertEqual(doc.toprettyxml(' '), _NORMAL_MARKER_EXPORT)

    def test__purgeMarkers(self):
        from Products.GenericSetup.testing import IDummyMarker
        helpers = self._makeOne()
        obj = helpers.context
        self._populate(obj)
        self.failUnless(IDummyMarker.providedBy(obj))

        helpers._purgeMarkers()
        self.failIf(IDummyMarker.providedBy(obj))

    def test__initMarkers(self):
        from Products.GenericSetup.utils import PrettyDocument
        from Products.GenericSetup.testing import IDummyMarker
        helpers = self._makeOne()
        node = _getDocumentElement(_NORMAL_MARKER_EXPORT)
        helpers._initMarkers(node)
        self.failUnless(IDummyMarker.providedBy(helpers.context))

        doc = helpers._doc = PrettyDocument()
        node = doc.createElement('dummy')
        node.appendChild(helpers._extractMarkers())
        doc.appendChild(node)

        self.assertEqual(doc.toprettyxml(' '), _NORMAL_MARKER_EXPORT)


class ObjectManagerHelpersTests(ZopeTestCase):

    def _getTargetClass(self):
        from Products.GenericSetup.utils import ObjectManagerHelpers

        return ObjectManagerHelpers

    def _makeOne(self, context=None, environ=None):
        from Products.GenericSetup.utils import NodeAdapterBase
        from Products.GenericSetup.testing import DummySetupEnviron

        class Foo(self._getTargetClass(), NodeAdapterBase):
            pass

        if context is None:
            context = self._makeContext()

        if environ is None:
            environ = DummySetupEnviron()

        return Foo(context, environ)

    def _makeContext(self):
        from OFS.ObjectManager import ObjectManager
        return ObjectManager('obj')

    def test__initObjects(self):
        helpers = self._makeOne()
        obj = helpers.context
        self.failIf('history' in obj.objectIds())

        # Add object
        node = _getDocumentElement(_ADD_IMPORT)
        helpers._initObjects(node)
        self.failUnless('history' in obj.objectIds())

        # Remove it again
        node = _getDocumentElement(_REMOVE_IMPORT)
        helpers._initObjects(node)
        self.failIf('history' in obj.objectIds())
        
        # Removing it a second time should not throw an
        # AttributeError.
        node = _getDocumentElement(_REMOVE_IMPORT)
        helpers._initObjects(node)
        self.failIf('history' in obj.objectIds())
        

class PrettyDocumentTests(unittest.TestCase):

    def test_attr_quoting(self):
        from Products.GenericSetup.utils import PrettyDocument
        original = 'baz &nbsp;<bar>&"\''
        expected = ('<?xml version="1.0"?>\n'
                    '<doc foo="baz &amp;nbsp;&lt;bar&gt;&amp;&quot;\'"/>\n')

        doc = PrettyDocument()
        node = doc.createElement('doc')
        node.setAttribute('foo', original)
        doc.appendChild(node)
        self.assertEqual(doc.toprettyxml(' '), expected)
        # Reparse
        e = _getDocumentElement(expected)
        self.assertEqual(e.getAttribute('foo'), original)

    def test_text_quoting(self):
        from Products.GenericSetup.utils import PrettyDocument
        original = 'goo &nbsp;<hmm>&"\''
        expected = ('<?xml version="1.0"?>\n'
                    '<doc>goo &amp;nbsp;&lt;hmm&gt;&amp;"\'</doc>\n')

        doc = PrettyDocument()
        node = doc.createElement('doc')
        child = doc.createTextNode(original)
        node.appendChild(child)
        doc.appendChild(node)
        self.assertEqual(doc.toprettyxml(' '), expected)
        # Reparse
        e = _getDocumentElement(expected)
        self.assertEqual(e.childNodes[0].nodeValue, original)


def test_suite():
    # reimport to make sure tests are run from Products
    from Products.GenericSetup.tests.test_utils import UtilsTests

    return unittest.TestSuite((
        unittest.makeSuite(UtilsTests),
        unittest.makeSuite(PropertyManagerHelpersTests),
        unittest.makeSuite(PropertyManagerHelpersNonPMContextTests),
        unittest.makeSuite(MarkerInterfaceHelpersTests),
        unittest.makeSuite(ObjectManagerHelpersTests),
        unittest.makeSuite(PrettyDocumentTests),
        ))

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