From 968c420fb925ed9fc468c1ba3cef4d998f507e94 Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine <arnaud.fontaine@nexedi.com> Date: Mon, 1 Nov 2010 06:27:17 +0000 Subject: [PATCH] Add tests to check the consistency when importing filesystem Property Sheets into ZODB git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@39738 20353a03-c40f-0410-a6d1-a30d3c3de9de --- .../tests/testDynamicClassGeneration.py | 205 +++++++++++++++++- 1 file changed, 204 insertions(+), 1 deletion(-) diff --git a/product/ERP5Type/tests/testDynamicClassGeneration.py b/product/ERP5Type/tests/testDynamicClassGeneration.py index b11c036b47..9c2b478206 100644 --- a/product/ERP5Type/tests/testDynamicClassGeneration.py +++ b/product/ERP5Type/tests/testDynamicClassGeneration.py @@ -29,8 +29,8 @@ ############################################################################## import unittest - import transaction + from Products.ERP5Type.dynamic.portal_type_class import synchronizeDynamicModules from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.backportUnittest import expectedFailure, skip @@ -694,8 +694,211 @@ class TestZodbPropertySheet(ERP5TypeTestCase): TestZodbPropertySheet = skip("ZODB Property Sheets code is not enabled yet")( TestZodbPropertySheet) +from Products.ERP5Type import PropertySheet +from Products.CMFCore.Expression import Expression + +from Products.ERP5Type.PropertySheet.StandardProperty import StandardProperty +from Products.ERP5Type.PropertySheet.AcquiredProperty import AcquiredProperty + +class TestZodbImportFilesystemPropertySheet(ERP5TypeTestCase): + """ + Check that importing filesystem Property Sheets into ZODB the same + properties and their values + """ + # The following fields of properties are no longer defined in ZODB + # Property Sheets because they have been deprecated + deprecated_field_name_tuple = ('mode', + 'select_variable', + 'label', + 'acquisition_depends', + 'acquisition_sync_value') + + def afterSetUp(self): + # Get all the property sheets defined on the filesystem + self.filesystem_property_sheet_list = [] + for name, klass in PropertySheet.__dict__.iteritems(): + if name[0] != '_': + self.filesystem_property_sheet_list.append(klass) + + # Mapping between the field name of a property and the default + # value as defined in StandardProperty and AcquiredProperty, + # meaningful because exporting a property relies on accessor which + # returns the default value if the field value is not set + self.filesystem_field_default_value_dict = {} + for property_dict in StandardProperty._properties + AcquiredProperty._properties: + try: + self.filesystem_field_default_value_dict[property_dict['id']] = \ + property_dict['default'] + except KeyError: + # Some fields may not defined a default value (such as 'id') + continue + + def _checkPropertyField(self, + property_sheet_name, + field_name, + filesystem_value, + zodb_value): + """ + Check whether the given filesystem property value and the given + ZODB property value are equal + """ + if isinstance(zodb_value, (list, tuple)): + self.failIfDifferentSet( + zodb_value, filesystem_value, + msg="%s: %s: filesystem value: %s, ZODB value: %s" % \ + (property_sheet_name, field_name, filesystem_value, zodb_value)) + + else: + # In ZODB Property Sheets, we have to get the TALES Expression + # as a string for properties, which used to be Expression in + # filesystem Property Sheets or are now Expression (because they + # used to be defined as Python types, such as tuple or int...) + if isinstance(zodb_value, Expression): + # In filesystem Property Sheets, acquisition_portal_type and + # portal_type, might be instances of Expression + if isinstance(filesystem_value, Expression): + zodb_value = zodb_value.text + filesystem_value = filesystem_value.text + # Otherwise, just convert the filesystem value to a TALES + # Expression string + else: + zodb_value = zodb_value.text + filesystem_value = 'python: ' + repr(filesystem_value) + + self.failUnlessEqual( + zodb_value, filesystem_value, + msg="%s: %s: filesystem value: %s, ZODB value: %s" % \ + (property_sheet_name, field_name, filesystem_value, + zodb_value)) + + def _checkPropertyDefinitionTuple(self, + property_sheet_name, + filesystem_property_tuple, + zodb_property_tuple): + """ + Check whether all properties have been properly converted from + the filesystem to the ZODB Property Sheet + """ + # Check whether all the properties are present in the given ZODB + # Property Sheet + self.assertEqual( + len(filesystem_property_tuple), len(zodb_property_tuple), + msg="%s: too many properties: filesystem: %s, ZODB: %s" % \ + (property_sheet_name, filesystem_property_tuple, zodb_property_tuple)) + + # Map filesystem property IDs to their definition + filesystem_property_id_dict = {} + for property_dict in filesystem_property_tuple: + filesystem_property_id_dict[property_dict['id']] = property_dict + + # Check each property defined in ZODB against the filesystem dict + # defined before + for zodb_property_dict in zodb_property_tuple: + # Meaningful to ensure that there is no missing field within a + # property + validated_field_counter = 0 + + filesystem_property_dict = \ + filesystem_property_id_dict[zodb_property_dict['id']] + + # Check each property field + for field_name, zodb_value in zodb_property_dict.iteritems(): + if field_name in filesystem_property_dict: + self._checkPropertyField(property_sheet_name, + field_name, + filesystem_property_dict[field_name], + zodb_value) + # As we are using accessors when exporting the ZODB Property + # Sheet to its filesystem definition, there may be additional + # fields set to their default value + elif field_name in self.filesystem_field_default_value_dict: + self.assertEqual( + self.filesystem_field_default_value_dict[field_name], + zodb_value, + msg="%s: Wrong default value %s for %s" % \ + (property_sheet_name, zodb_value, field_name)) + + validated_field_counter += 1 + + if len(filesystem_property_dict) != validated_field_counter: + missing_field_name_list = [ + k for k in filesystem_property_dict \ + if k not in zodb_property_dict and \ + k not in self.deprecated_field_name_tuple ] + + self.assertTrue( + len(missing_field_name_list) == 0, + msg="%s: missing fields: %s: filesystem: %s, ZODB: %s" % \ + (property_sheet_name, missing_field_name_list, + filesystem_property_dict, zodb_property_dict)) + + def _checkCategoryTuple(self, + property_sheet_name, + filesystem_category_tuple, + zodb_category_tuple): + """ + Check whether all categories have been properly converted + """ + # There should be the same number of categories + self.assertEqual( + len(filesystem_category_tuple), len(zodb_category_tuple), + msg="%s: Missing/added categories: filesystem: %s, ZODB: %s" % \ + (property_sheet_name, filesystem_category_tuple, zodb_category_tuple)) + + # Some Categories are instance of Expression, so compute a list of + # categories as strings + zodb_category_list = [ + isinstance(category, Expression) and category.text or category \ + for category in zodb_category_tuple ] + + # Now, compare filesystem categories with ZODB + for category in filesystem_category_tuple: + if isinstance(category, Expression): + category = category.text + + self.assertTrue( + category in zodb_category_list, + msg="%s: Missing category %s: ZODB: %s" % \ + (property_sheet_name, category, zodb_category_list)) + + def testZodbImportPropertySheet(self): + """ + Create Property Sheets on portal_property_sheets from their + definition on the filesystem and then test that they are + equivalent + + TODO: Constraints + """ + portal = self.getPortalObject().portal_property_sheets + + for filesystem_property_sheet in self.filesystem_property_sheet_list: + property_sheet_name = filesystem_property_sheet.__name__ + + # Rename the filesystem Property Sheet class to avoid clashing + # with existing Property Sheets in portal_property_sheets + filesystem_property_sheet.__name__ = "%s_%s" % \ + (self.__class__.__name__, property_sheet_name) + + zodb_property_sheet = portal.createPropertySheetFromFilesystemClass( + filesystem_property_sheet) + + zodb_property_tuple, zodb_category_tuple, zodb_constraint_tuple = \ + portal.exportPropertySheetToFilesystemDefinitionTuple( + zodb_property_sheet) + + self._checkPropertyDefinitionTuple(property_sheet_name, + getattr(filesystem_property_sheet, + '_properties', []), + zodb_property_tuple) + + self._checkCategoryTuple(property_sheet_name, + getattr(filesystem_property_sheet, + '_categories', []), + zodb_category_tuple) + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestPortalTypeClass)) suite.addTest(unittest.makeSuite(TestZodbPropertySheet)) + suite.addTest(unittest.makeSuite(TestZodbImportFilesystemPropertySheet)) return suite -- 2.30.9