test.erp5.testBusinessPackage.py 11.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
##############################################################################
#
# Copyright (c) 2002-2017 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################

from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
29
import time
30
from Products.ERP5.Document.BusinessPackage import InstallationTree, createInstallationData
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

class TestBusinessPackage(ERP5TypeTestCase):
  """
  Test class to test that Business Package object can export some paths
  and install them on an erp5 site

  Steps:
  - Create BusinessPackage object
  - Add path list to the object
  - Build the package and expect the items mentioned in path list gets
  exported in the build step
  - Remove the objects mentioned in path_list from the site
  - Install the package
  - Expected result should be that it installs the objects on the site
  """

  def getTitle(self):
    return "TestBusinessPackage"

  def getBusinessTemplateList(self):
    """
    Tuple of Business Templates we need to install
    """
    return (
      'erp5_base',
56
      'erp5_core',
Ayush Tiwari's avatar
Ayush Tiwari committed
57
      'erp5_dms',
58
      'erp5_property_sheets',
59 60 61 62 63 64 65 66
      'erp5_business_package',
      )

  def afterSetUp(self):
    """
    This is ran before anything, used to set the environment
    """
    # here, you can create the categories and objects your test will depend on
67
    #self.export_dir = tempfile.mkdtmp(dir=tests_home)
68 69 70 71 72 73 74 75 76 77 78
    self.portal = self.getPortalObject()

  def beforeTearDown(self):
    try:
      package_id  = self.package.getId()
      if package_id:
        self.portal.manage_delObjects([package_id,]) 
    except AttributeError:
      pass

  def _createBusinessPackage(self):
79 80 81 82
    new_id = 'package_%s'%str(time.time())
    package = self.portal.newContent(id=new_id, portal_type='Business Package')
    #self.assertTrue(package.getBuildingState() == 'draft')
    #self.assertTrue(package.getInstallationState() == 'not_installed')
83 84 85
    package.edit(title ='test_package',
                  version='1.0',
                  description='package for live test')
86
    self.tic()
87 88
    return package

89
  def _buildAndExportBusinessPackage(self, package):
90 91 92 93 94 95 96
    """
    Builds and exports Business Package to a given export directory
    """
    # Build Package
    # Expected result should be while building the path object items
    # are going to be exported as XML(?)
    self.tic()
97
    package.build()
98 99 100 101 102 103
    self.tic()

    # Export package (not needed)
    #self.package.export(path=self.export_dir, local=True)
    #self.tic()

104
  def _installBusinessPackage(self, package):
105 106 107 108
    """
    Install the package from its built version.
    Expected to install the PathTemplateObject items
    """
109
    package.install()
110 111 112

  def test_fileImportAndReinstallForDocument(self):
    """
113 114 115
    Test Business Package build and install with test document.

    Expected result: Installs the exported object to the path expected on site.
116
    """
117
    package = self._createBusinessPackage()
118 119 120 121 122 123 124 125 126
    document_file = self.portal.document_module.newContent(
                                    portal_type = 'File',
                                    title = 'Test Document',
                                    reference = 'erp5-package.Test.Document',
                                    data = 'test file',
                                    content_type = None)
    self.tic()

    file_path = document_file.getRelativeUrl()
127
    package.edit(template_path_list=[file_path,])
128 129

    # Build package
130
    self._buildAndExportBusinessPackage(package)
131 132 133 134 135 136

    # Delete document from site
    self.portal.document_module.manage_delObjects([document_file.getId(),])
    self.tic()

    # Test if the file is gone
137
    self.assertRaises(KeyError, lambda: self.portal.restrictedTraverse(file_path))
138 139

    # Install package
140
    self._installBusinessPackage(package)
141 142 143

    # Test if the file is back
    self.assertIsNotNone(self.portal.restrictedTraverse(file_path))
144 145
    document = self.portal.restrictedTraverse(file_path)
    self.assertEquals(document.title, 'Test Document')
146 147 148

  def test_sameFileImportAndReinstallOnTwoPackages(self):
    """
149 150
    Test two Business Packages build and installation of same file.

151 152 153
    Here we will be using Insatallation Tree to install in the two packages
    all together, rather than doing installation one after another.

154 155 156
    Expected result: If we install same object from 2 different business packages,
    then in that case the installation object should compare between the
    state of OFS and installation and install accordingly.
157
    """
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

    old_package = self._createBusinessPackage()
    new_package = self._createBusinessPackage()

    document_file = self.portal.document_module.newContent(
                                    portal_type = 'File',
                                    title = 'Test Document',
                                    reference = 'erp5-package.Test.Document.Two.BP',
                                    data = 'test file',
                                    content_type = None)
    self.tic()

    file_path = document_file.getRelativeUrl()
    old_package.edit(template_path_list=[file_path,])
    new_package.edit(template_path_list=[file_path,])
    self.tic()

    # Build both the packages
    self._buildAndExportBusinessPackage(old_package)
    self._buildAndExportBusinessPackage(new_package)
    self.tic()

    # Get installation data from the list of packages which we want to install
    package_list = [old_package, new_package]

183
    final_data, conflicted_data = createInstallationData(package_list)
184 185 186 187 188 189 190 191

    # Delete document from site
    self.portal.document_module.manage_delObjects([document_file.getId(),])
    self.tic()

    # Test if the file doesn't exist on site anymore
    self.assertRaises(KeyError, lambda: self.portal.restrictedTraverse(file_path))

192 193 194 195 196 197 198 199 200 201 202 203
    if not conflicted_data:
      # Create InstallationTree object
      installation_tree = InstallationTree(final_data)
      # We try to install pakcages via mapping the installation tree to ZODB
      # As both have exactly same document we expect that only one of them get installed
      installation_tree.mapToERP5Site(self.portal)


    # Test if the file is back
    self.assertIsNotNone(self.portal.restrictedTraverse(file_path))
    document = self.portal.restrictedTraverse(file_path)
    self.assertEquals(document.title, document_file.title)
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

  def test_AddConflictedFileAtSamePathViaTwoPackages(self):
    """
    Test the result of conflict of two files to be installed at same path
    by two different Business Packages
    """
    old_package = self._createBusinessPackage()
    new_package = self._createBusinessPackage()

    document_file = self.portal.document_module.newContent(
                                    portal_type = 'File',
                                    title = 'Test Document',
                                    reference = 'erp5-package.Test.Document.Two.BP',
                                    data = 'test file',
                                    content_type = None)
    self.tic()

    file_path = document_file.getRelativeUrl()
    old_package.edit(template_path_list=[file_path,])

    # Build the first package
    self._buildAndExportBusinessPackage(old_package)
    self.tic()

    # Change something in the document file
    document_file.edit(data='Voila, we place with conflict')
    self.tic()
    new_package.edit(template_path_list=[file_path,])

    # Build the second package
    self._buildAndExportBusinessPackage(new_package)
    self.tic()

    # Get installation data from the list of packages which we want to install
    package_list = [old_package, new_package]

    final_data, conflicted_data = createInstallationData(package_list)

    # Delete document from site
    self.portal.document_module.manage_delObjects([document_file.getId(),])
    self.tic()

    # Assert that the final data is empty and conflicted data contains \
    # two different versions of the file
    self.assertFalse(final_data)
    self.assertTrue(conflicted_data)
    self.assertEquals(len(conflicted_data[file_path]), 2)
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

  def test_checkPathTemplatBuildForFolder(self):
    """
    This test should ensure that we are able to use folder as path for Business
    Packages without the need to export every path inside it explicitly

    In this test, we take the example to do this first with default catalog,
    then with multiple catalogs
    """

    # With single catalog
    folder_path = 'portal_catalog/erp5_mysql_innodb/**'
    package = self._createBusinessPackage()
    package.edit(template_path_list=[folder_path,])
    self._buildAndExportBusinessPackage(package)
    self.tic()

    # Check for the presence of catalog objects/paths in the business package
    built_package = self.portal._getOb(package.getId())
    path_item = built_package._path_item

    folder = self.portal.unrestrictedTraverse('portal_catalog/erp5_mysql_innodb')
    folder_object_id_list = sorted([l for l in folder.objectIds()])
    folder_object_count =  len(folder_object_id_list)

    package_object_id_list = sorted([l.getId() for l in path_item._objects.values()])
    package_object_count = len(package_object_id_list)

    self.assertEquals(folder_object_count, package_object_count)
    self.assertEquals(folder_object_id_list, package_object_id_list)

    # With multiple catalogs
    folder_path_list = [ 
          'portal_catalog/erp5_mysql_innodb/**',
          'portal_catalog/erp5_mysql_innodb100/**'
          ]

    package.edit(template_path_list=folder_path_list)
    self.tic()
    # XXX: Here, we are not exporting the package and its objects, just building
    # and saving it inside the package for the tests.
    self._buildAndExportBusinessPackage(package)
    self.tic()

    # Check for presence of catalog objects from all the catalogs mentioned in
    # the folder path list
    built_package = self.portal._getOb(package.getId())
    path_item = built_package._path_item
    new_folder = self.portal.unrestrictedTraverse('portal_catalog/erp5_mysql_innodb100')
    new_folder_id_list = sorted([l for l in new_folder.objectIds()])
    new_folder_object_count =  len(new_folder_id_list)

    total_object_count  = new_folder_object_count + folder_object_count
    package_object_id_list = sorted([l.getId() for l in path_item._objects.values()])
    object_id_list = sorted(folder_object_id_list + new_folder_id_list) 
    package_object_count = len(package_object_id_list)
    self.assertEquals(total_object_count, package_object_count)
    self.assertEquals(object_id_list, package_object_id_list)