testTemplateTool.py 28.8 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 29
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SARL and Contributors. All Rights Reserved.
#          Aurelien Calonne <aurel@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability 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
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################

30 31
import os
import shutil
32
import unittest
33
import random
34
import tempfile
35 36 37 38 39
from App.config import getConfiguration
from Products.ERP5VCS.WorkingCopy import getVcsTool

from Products.ERP5.Document.BusinessTemplate import \
    BusinessTemplateMissingDependency
40

41 42
from Products.ERP5.Tool.TemplateTool import BusinessTemplateUnknownError

43 44 45 46 47 48 49 50
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase

class TestTemplateTool(ERP5TypeTestCase):
  """
  Test the template tool
  """
  run_all_test = 1
  quiet = 1
51
  test_tool_id = 'test_portal_templates'
52 53

  def getBusinessTemplateList(self):
54
    return ('erp5_core_proxy_field_legacy',
55
            'erp5_full_text_mroonga_catalog',
56
            'erp5_base',
57
            'erp5_stock_cache',
58
            'erp5_csv_style')
59 60 61 62 63 64

  def getTitle(self):
    return "Template Tool"

  def afterSetUp(self):
    self.templates_tool = self.portal.portal_templates
65 66
    self.setupAutomaticBusinessTemplateRepository(
         searchable_business_template_list=["erp5_core", "erp5_base"])
67 68 69 70 71
    if getattr(self.portal, self.test_tool_id, None) is not None:
      self.portal.manage_delObjects(ids=[self.test_tool_id])
    self.portal.newContent(portal_type='Template Tool',
                           id=self.test_tool_id)
    self.dummy_template_tool = getattr(self.portal, self.test_tool_id)
72

73
  def beforeTearDown(self):
74
    self.tic()
75 76
    mark_replaced_bt_list = ["erp5_odt_style", "erp5_pdm", 'erp5_accounting',
           'erp5_workflow', 'erp5_configurator', 'erp5_configurator_ung',
77
           'erp5_ingestion_mysql_innodb_catalog', "erp5_configurator_standard"]
78
    for bt_name in mark_replaced_bt_list:
79
      bt = self.templates_tool.getInstalledBusinessTemplate(bt_name)
80 81 82
      if (bt is not None) and bt.getInstallationState() in ['installed',
                                                            'replaced']:
        self.templates_tool.manage_delObjects([bt.getId()])
83
    self.tic()
84 85 86
    bt = self.templates_tool.getInstalledBusinessTemplate("erp5_base")
    if bt.getInstallationState() == "replaced":
      bt.install(force=1)
87
    self.tic()
88

89 90 91 92 93 94 95 96
  def checkFolderReindexAllActivityPresense(self):
    message_list = [m for m in self.portal.portal_activities.getMessageList()
                      if m.method_id == 'Folder_reindexAll']
    self.assertNotEquals(len(message_list), 0)

  def checkFolderReindexAllActivityNotPresent(self):
    message_list = [m for m in self.portal.portal_activities.getMessageList()
                      if m.method_id == 'Folder_reindexAll']
97
    self.assertEqual(len(message_list), 0)
98

99 100 101
  def testUpdateBT5FromRepository(self, quiet=quiet, run=run_all_test):
    """ Test the list of bt5 returned for upgrade """
    # edit bt5 revision so that it will be marked as updatable
102 103 104 105 106 107 108 109 110 111
    erp5_base = self.templates_tool.getInstalledBusinessTemplate('erp5_base',
                                                                 strict=True)
    erp5_base._setRevision('')

    self.assertTrue("erp5_base" in (bt.getTitle() for bt in
      self.templates_tool.getRepositoryBusinessTemplateList(update_only=True)))
    erp5_base.replace()
    self.assertFalse("erp5_base" in (bt.getTitle() for bt in
      self.templates_tool.getRepositoryBusinessTemplateList(update_only=True)))
    self.abort()
112

113 114 115
  def test_download_http(self):
    test_web = self.portal.portal_templates.download(
        'http://www.erp5.org/dists/snapshot/test_bt5/test_web.bt5')
116 117
    self.assertEqual(test_web.getPortalType(), 'Business Template')
    self.assertEqual(test_web.getTitle(), 'test_web')
118
    self.assertEqual(len(test_web.getRevision()), 28)
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

  def _svn_setup_ssl(self):
    """
      Function used to trust in svn.erp5.org.
    """
    trust_dict = dict(realm="https://svn.erp5.org:443",
      hostname="roundcube.nexedi.com",
      issuer_dname="Nexedi SA, Marcq en Baroeul, Nord Pas de Calais, FR",
      valid_from="Thu, 22 May 2008 13:43:01 GMT",
      valid_until="Sun, 20 May 2018 13:43:01 GMT",
      finger_print=\
        "a1:f7:c6:bb:51:69:84:28:ac:58:af:9d:05:73:de:24:45:4d:a1:bb",
      failures=8)
    getVcsTool("svn").__of__(self.portal).acceptSSLServer(trust_dict)

  def test_download_svn(self):
    # if the page looks like a svn repository, template tool will use pysvn to
    # get the bt5.
    self._svn_setup_ssl()
    bt5_url = 'https://svn.erp5.org/repos/public/erp5/trunk/bt5/test_web'
    test_web = self.portal.portal_templates.download(bt5_url)
140 141
    self.assertEqual(test_web.getPortalType(), 'Business Template')
    self.assertEqual(test_web.getTitle(), 'test_web')
142
    self.assertEqual(len(test_web.getRevision()), 28)
143 144 145 146 147

  def test_updateBusinessTemplateFromUrl_simple(self):
    """
     Test updateBusinessTemplateFromUrl method

148
     By default if a new business template has revision != previous one
149 150 151 152 153
     the new bt5 is not installed, only imported.
    """
    self._svn_setup_ssl()
    template_tool = self.portal.portal_templates
    old_bt = template_tool.getInstalledBusinessTemplate('erp5_csv_style')
154 155
    # fake different revision
    old_bt.setRevision('')
156 157 158 159
    url = 'https://svn.erp5.org/repos/public/erp5/trunk/bt5/erp5_csv_style'
    template_tool.updateBusinessTemplateFromUrl(url)
    new_bt = template_tool.getInstalledBusinessTemplate('erp5_csv_style')
    self.assertNotEquals(old_bt, new_bt)
160
    self.assertEqual('erp5_csv_style', new_bt.getTitle())
161 162 163

    # Test Another time with definning an ID
    old_bt = new_bt
164
    old_bt.setRevision('')
165 166 167
    template_tool.updateBusinessTemplateFromUrl(url, id="new_erp5_csv_style")
    new_bt = template_tool.getInstalledBusinessTemplate('erp5_csv_style')
    self.assertNotEquals(old_bt, new_bt)
168 169
    self.assertEqual('erp5_csv_style', new_bt.getTitle())
    self.assertEqual('new_erp5_csv_style', new_bt.getId())
170 171 172 173 174

    # Test if the new instance with same revision is not installed.
    old_bt = new_bt
    template_tool.updateBusinessTemplateFromUrl(url, id="not_installed_bt5")
    new_bt = template_tool.getInstalledBusinessTemplate('erp5_csv_style')
175 176 177
    self.assertEqual(old_bt, new_bt)
    self.assertEqual('erp5_csv_style', new_bt.getTitle())
    self.assertEqual('new_erp5_csv_style', new_bt.getId())
178
    not_installed_bt5 = template_tool['not_installed_bt5']
179 180
    self.assertEqual('erp5_csv_style', not_installed_bt5.getTitle())
    self.assertEqual(not_installed_bt5.getInstallationState(),
181
                      "not_installed")
182
    self.assertEqual(not_installed_bt5.getRevision(), new_bt.getRevision())
183 184 185 186 187 188 189 190 191

  def test_updateBusinessTemplateFromUrl_keep_list(self):
    """
     Test updateBusinessTemplateFromUrl method
    """
    self._svn_setup_ssl()
    template_tool = self.portal.portal_templates
    url = 'https://svn.erp5.org/repos/public/erp5/trunk/bt5/test_core'
    # don't install test_file
Rafael Monnerat's avatar
Rafael Monnerat committed
192
    keep_original_list = ('portal_skins/erp5_test/test_file', )
193 194 195 196
    template_tool.updateBusinessTemplateFromUrl(url,
                                   keep_original_list=keep_original_list)
    bt = template_tool.getInstalledBusinessTemplate('test_core')
    self.assertNotEquals(None, bt)
197 198
    erp5_test = self.portal.portal_skins['erp5_test']
    self.assertFalse(erp5_test.hasObject('test_file'))
199 200 201 202 203 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

  def test_updateBusinessTemplateFromUrl_after_before_script(self):
    """
     Test updateBusinessTemplateFromUrl method
    """
    from Products.ERP5Type.tests.utils import createZODBPythonScript
    portal = self.getPortal()
    self._svn_setup_ssl()
    createZODBPythonScript(portal.portal_skins.custom,
                                   'BT_dummyA',
                                   'scripts_params=None',
                                   '# Script body\n'
                                   'return context.setDescription("MODIFIED")')

    createZODBPythonScript(portal.portal_skins.custom,
                                   'BT_dummyB',
                                   'scripts_params=None',
                                   '# Script body\n'
                                   'return context.setChangeLog("MODIFIED")')

    createZODBPythonScript(portal.portal_skins.custom,
                                   'BT_dummyC',
                                   'scripts_params=None',
                                   '# Script body\n'
                                   'return context.getPortalObject().setTitle("MODIFIED")')

    template_tool = self.portal.portal_templates
    url = 'https://svn.erp5.org/repos/public/erp5/trunk/bt5/test_html_style'
    # don't install test_file
    before_triggered_bt5_id_list = ['BT_dummyA', 'BT_dummyB']
    after_triggered_bt5_id_list = ['BT_dummyC']
    template_tool.updateBusinessTemplateFromUrl(url,
                                   before_triggered_bt5_id_list=before_triggered_bt5_id_list,
                                   after_triggered_bt5_id_list=after_triggered_bt5_id_list)
    bt = template_tool.getInstalledBusinessTemplate('test_html_style')
    self.assertNotEquals(None, bt)
235 236 237
    self.assertEqual(bt.getDescription(), 'MODIFIED')
    self.assertEqual(bt.getChangeLog(), 'MODIFIED')
    self.assertEqual(portal.getTitle(), 'MODIFIED')
238 239 240 241

  def test_CompareVersions(self):
    """Tests compare version on template tool. """
    compareVersions = self.getPortal().portal_templates.compareVersions
242 243 244 245
    self.assertEqual(0, compareVersions('1', '1'))
    self.assertEqual(0, compareVersions('1.2', '1.2'))
    self.assertEqual(0, compareVersions('1.2rc3', '1.2rc3'))
    self.assertEqual(0, compareVersions('1.0.0', '1.0'))
246

247 248 249 250
    self.assertEqual(-1, compareVersions('1.0', '1.0.1'))
    self.assertEqual(-1, compareVersions('1.0rc1', '1.0'))
    self.assertEqual(-1, compareVersions('1.0a', '1.0.1'))
    self.assertEqual(-1, compareVersions('1.1', '2.0'))
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265

  def test_CompareVersionStrings(self):
    """Test compareVersionStrings on template tool"""
    compareVersionStrings = \
        self.getPortal().portal_templates.compareVersionStrings
    self.assertTrue(compareVersionStrings('1.1', '> 1.0'))
    self.assertFalse(compareVersionStrings('1.1rc1', '= 1.0'))
    self.assertFalse(compareVersionStrings('1.0rc1', '> 1.0'))
    self.assertFalse(compareVersionStrings('1.0rc1', '>= 1.0'))
    self.assertTrue(compareVersionStrings('1.0rc1', '>= 1.0rc1'))

  def test_getInstalledBusinessTemplate(self):
    self.assertNotEquals(None, self.getPortal()\
        .portal_templates.getInstalledBusinessTemplate('erp5_core'))

266
    self.assertEqual(None, self.getPortal()\
267 268
        .portal_templates.getInstalledBusinessTemplate('erp5_toto'))

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
  def test_revision(self):
    template_tool = self.portal.portal_templates
    getInstalledRevision = template_tool.getInstalledBusinessTemplateRevision
    self.assertEqual(None, getInstalledRevision('erp5_toto'))
    available_bt, = template_tool.getRepositoryBusinessTemplateList(
      template_list=('test_core',))
    revision = available_bt.getRevision()
    self.assertEqual('PN8VPt52MbdHtxfjKvL+MBsNbzM=', revision)
    installed_bt = template_tool.download("%s/%s" % (available_bt.repository,
                                                     available_bt.filename))
    self.assertEqual(revision, installed_bt.getRevision())
    installed_bt.install()
    self.assertEqual(revision, getInstalledRevision('test_core'))
    bt = installed_bt.Base_createCloneDocument(batch_mode=1)
    bt.build(update_revision=False)
    root = tempfile.mkdtemp()
    try:
      bt.export(root, local=1)
      with open(os.path.join(root, 'bt', 'title')) as f:
        self.assertTrue('test_core', f.read())
      # We don't export revision anymore.
      self.assertFalse(os.path.exists(os.path.join(root, 'bt', 'revision')))
      # Computed at download ...
      self.assertEqual(revision, template_tool.download(root).getRevision())
    finally:
      shutil.rmtree(root)
    bt._setVersion("2.0")
    # ... at building by default ...
    bt.build()
    revision = bt.getRevision()
    self.assertEqual('tPNr/gGXaa0fYCsFUWe8nqzSNLc=', revision)
    self.portal.portal_skins.erp5_test.manage_renameObject('test_file',
                                                           'test_file2')
    bt.build(update_revision=False)
    self.assertEqual(revision, bt.getRevision())
    # ... and at export.
    bt.export(str(random.random()))
    self.assertEqual('Nup/xsO1xpsmdJ5GTdknuVJyOr8=', bt.getRevision())
    self.abort()
308

309 310 311
  def test_getInstalledBusinessTemplateList(self):
    templates_tool = self.getPortal().portal_templates
    bt5_list = templates_tool.getInstalledBusinessTemplateList()
Rafael Monnerat's avatar
Rafael Monnerat committed
312
    another_bt_list = [i for i in templates_tool.contentValues() \
313
                       if i.getInstallationState() == 'installed']
314
    self.assertEqual(len(bt5_list), len(another_bt_list))
315
    for bt in bt5_list:
316
      self.assertTrue(bt in another_bt_list)
317

318
    self.assertEqual(bt5_list,
319 320 321 322
                      templates_tool._getInstalledBusinessTemplateList())

  def test_getInstalledBusinessTemplateTitleList(self):
    templates_tool = self.getPortal().portal_templates
Rafael Monnerat's avatar
Rafael Monnerat committed
323 324
    bt5_list = templates_tool.getInstalledBusinessTemplateTitleList()
    another_bt_list = [i.getTitle() for i in templates_tool.contentValues() \
325 326 327
                       if i.getInstallationState() == 'installed']
    bt5_list.sort()
    another_bt_list.sort()
328
    self.assertEqual(bt5_list, another_bt_list)
329
    for bt in bt5_list:
330
      self.assertTrue(bt in another_bt_list)
331 332 333

    new_list = templates_tool._getInstalledBusinessTemplateList(only_title=1)
    new_list.sort()
334
    self.assertEqual(bt5_list, new_list)
335 336 337 338 339 340

  def test_getBusinessTemplateUrl(self):
    """ Test if this method can find which repository is the business
        template
    """
    # How to define an existing and use INSTANCE_HOME_REPOSITORY?
Rafael Monnerat's avatar
Rafael Monnerat committed
341 342 343 344 345
    url_list = ['https://svn.erp5.org/repos/public/erp5/trunk/bt5',
                'http://www.erp5.org/dists/snapshot/bt5',
                'http://www.erp5.org/dists/release/5.4.5/bt5',
                "INSTANCE_HOME_REPOSITORY",
                'file:///opt/does/not/exist']
346 347 348 349 350 351 352

    exist_bt5 = 'erp5_base'
    not_exist_bt5 = "erp5_not_exist"
    template_tool = self.portal.portal_templates
    getBusinessTemplateUrl = template_tool.getBusinessTemplateUrl

    # Test Exists
353
    self.assertEqual(getBusinessTemplateUrl(url_list, exist_bt5),
354
                  'https://svn.erp5.org/repos/public/erp5/trunk/bt5/erp5_base')
355
    self.assertEqual(getBusinessTemplateUrl(url_list[1:], exist_bt5),
356
                      'http://www.erp5.org/dists/snapshot/bt5/erp5_base.bt5')
357
    self.assertEqual(getBusinessTemplateUrl(url_list[2:], exist_bt5),
358 359 360 361 362
                      'http://www.erp5.org/dists/release/5.4.5/bt5/erp5_base.bt5')
    INSTANCE_HOME = getConfiguration().instancehome
    local_bt = None
    if os.path.exists(INSTANCE_HOME + "/bt5/erp5_base"):
      local_bt = 'file://' + INSTANCE_HOME + "/bt5/erp5_base"
363 364
    self.assertEqual(getBusinessTemplateUrl(url_list[3:], exist_bt5), local_bt)
    self.assertEqual(getBusinessTemplateUrl(url_list[4:], exist_bt5), None)
365

366
    # Test Not exists
367 368 369 370 371
    self.assertEqual(getBusinessTemplateUrl(url_list, not_exist_bt5), None)
    self.assertEqual(getBusinessTemplateUrl(url_list[1:], not_exist_bt5), None)
    self.assertEqual(getBusinessTemplateUrl(url_list[2:], not_exist_bt5), None)
    self.assertEqual(getBusinessTemplateUrl(url_list[3:], not_exist_bt5), None)
    self.assertEqual(getBusinessTemplateUrl(url_list[4:], not_exist_bt5), None)
372 373 374 375 376

  def test_resolveBusinessTemplateListDependency(self):
    """ Test API able to return a complete list of bt5s to setup a sub set of
    business templates.
    """
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
    repository = "dummy_repository"
    template_tool = self.dummy_template_tool
    # setup dummy internal repository data to make unit test independant
    # from any real repository
    def addRepositoryEntry(**kw):
      kw['id'] = '%s.bt5' % kw['title']
      kw.setdefault('version', '1')
      kw.setdefault('provision_list', ())
      kw.setdefault('dependency_list', ())
      kw.setdefault('revision', '1')
      return kw
    template_tool.repository_dict[repository] = (
      addRepositoryEntry(title='foo', dependency_list=()),
      addRepositoryEntry(title='bar', dependency_list=('foo',)),
      addRepositoryEntry(title='baz', dependency_list=('bar',)),
      addRepositoryEntry(title='biz', dependency_list=()),
      addRepositoryEntry(title='ca1', provision_list=('sql',)),
      addRepositoryEntry(title='ca2', provision_list=('sql',)),
395 396 397
      addRepositoryEntry(title='a', dependency_list=()),
      addRepositoryEntry(title='b', dependency_list=('a'), revision='5'),
      addRepositoryEntry(title='end', dependency_list=('baz','sql', 'b')),
398 399 400
      )

    # Simulate that we have some installed bt.
401
    for bt_id in ('foo', 'ca1', 'b'):
402 403 404
      bt = template_tool.newContent(portal_type='Business Template',
                             title=bt_id, revision='4', id=bt_id)
      bt.install()
405

406
    bt5_id_list = ['baz']
407
    bt5_list = template_tool.resolveBusinessTemplateListDependency(bt5_id_list)
408
    self.assertEqual([(repository, 'foo.bt5'),
409
                       (repository, 'bar.bt5'),
410
                       (repository, 'baz.bt5')], bt5_list)
411

412
    bt5_id_list = ['foo']
413
    bt5_list = template_tool.resolveBusinessTemplateListDependency(
414
                      bt5_id_list)
415
    self.assertEqual([(repository, 'foo.bt5')], bt5_list)
416

417
    bt5_id_list = ['biz', 'end']
418 419

    bt5_list = template_tool.resolveBusinessTemplateListDependency(bt5_id_list)
420
    self.assertEqual([(repository, 'foo.bt5'),
421 422 423 424
                       (repository, 'a.bt5'),
                       (repository, 'bar.bt5'),
                       (repository, 'b.bt5'),
                       (repository, 'ca1.bt5'),
425
                       (repository, 'baz.bt5'),
426 427
                       (repository, 'end.bt5'),
                       (repository, 'biz.bt5')], bt5_list)
428

429 430 431
    # By removing ca1, we remove the choice for the "sql" provider.
    # Therefore template tool does not know any more what to take for "sql".
    template_tool.manage_delObjects(['ca1'])
432
    self.commit()
433 434
    self.assertRaises(BusinessTemplateMissingDependency,
                template_tool.resolveBusinessTemplateListDependency,
435
                bt5_id_list)
436

437 438 439
    bt5_id_list = ['erp5_do_not_exist']
    self.assertRaises(BusinessTemplateUnknownError,
                   template_tool.resolveBusinessTemplateListDependency,
440
                   bt5_id_list)
441 442 443 444 445

  def test_installBusinessTemplatesFromRepository_simple(self):
    """ Simple test for portal_templates.installBusinessTemplatesFromRepository
    """
    bt5_name = 'erp5_odt_style'
446
    self.tic()
447
    bt = self.templates_tool.getInstalledBusinessTemplate(bt5_name, strict=True)
448
    self.assertEqual(bt, None)
449 450
    operation_log = \
      self.templates_tool.installBusinessTemplateListFromRepository([bt5_name])
451
    self.assertTrue("Installed %s with" % bt5_name in operation_log[-1])
452 453
    bt = self.templates_tool.getInstalledBusinessTemplate(bt5_name, strict=True)
    self.assertNotEquals(bt, None)
454
    self.assertEqual(bt.getTitle(), bt5_name)
455 456 457 458

    # Repeat operation, the bt5 should be ignored
    self.templates_tool.installBusinessTemplateListFromRepository([bt5_name])
    bt_old = self.templates_tool.getInstalledBusinessTemplate(bt5_name, strict=True)
459
    self.assertEqual(bt.getId(), bt_old.getId())
460

461
    # Repeat operation, new bt5 should be inslalled due only_different = False
462
    operation_log = self.templates_tool.installBusinessTemplateListFromRepository(
463
          [bt5_name], only_different=False)
464

465
    self.assertTrue("Installed %s with" % bt5_name in operation_log[-1])
466 467 468 469 470 471 472
    bt_new = self.templates_tool.getInstalledBusinessTemplate(bt5_name,
                                                              strict=True)
    self.assertNotEquals(bt.getId(), bt_new.getId())

  def test_installBusinessTemplatesFromRepository_update_catalog(self):
    """ Test if update catalog is trigger when needed.
    """
473 474 475 476 477
    try:
      bt5_name = 'erp5_ingestion_mysql_innodb_catalog'
      template_tool = self.portal.portal_templates
      self.tic()
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
478
      self.assertEqual(bt, None)
479
      operation_log = template_tool.installBusinessTemplateListFromRepository([bt5_name],
480
                            only_different=False, update_catalog=0)
481

482 483 484 485 486
      self.assertTrue("Installed %s with" % bt5_name in operation_log[0])
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
      self.assertNotEquals(bt.getId(), None)
      self.commit()
      self.checkFolderReindexAllActivityNotPresent()
487 488 489 490 491
      # Before launch activities make sure email table is created even
      # catalog is not created.
      catalog_tool = self.portal.portal_catalog
      catalog_tool.erp5_mysql_innodb.z0_drop_email()
      catalog_tool.erp5_mysql_innodb.z_create_email()
492
      self.tic()
493

494 495
      bt5_name = 'erp5_odt_style'
      operation_log = template_tool.installBusinessTemplateListFromRepository([bt5_name],
496
                            only_different=False, update_catalog=1)
497
      self.assertTrue("Installed %s with" % bt5_name in operation_log[-1])
498
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
499
      self.assertEqual(bt.getTitle(), bt5_name)
500 501 502 503 504 505
      self.commit()
      self.checkFolderReindexAllActivityPresense()
      self.tic()

      # Install again should not force catalog to be updated
      operation_log = template_tool.installBusinessTemplateListFromRepository(
506
                [bt5_name], only_different=False)
507
      self.assertTrue("Installed %s with" % bt5_name in operation_log[-1])
508 509
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
      self.assertNotEquals(bt, None)
510
      self.assertEqual(bt.getTitle(), bt5_name)
511 512 513 514 515 516 517 518 519 520 521
      self.commit()
      self.checkFolderReindexAllActivityNotPresent()
      self.tic()
    finally:
      # Make sure no broken catalog it will be left behind and propaguated to
      # the next tests.
      if len(self.portal.portal_activities.getMessageList())>0:
        self.portal.portal_activities.manageClearActivities()
        self.commit()
        self.portal.ERP5Site_reindexAll(clear_catalog=1)
      self.tic()
522 523 524 525 526

  def test_installBusinessTemplatesFromRepository_activate(self):
    """ Test if update catalog is trigger when needed.
    """
    bt5_name_list = ['erp5_odt_style', 'erp5_pdm']
527
    self.tic()
528 529
    for bt5_name in bt5_name_list:
      bt = self.templates_tool.getInstalledBusinessTemplate(bt5_name)
530
      self.assertEqual(bt, None)
531 532 533 534 535 536

    self.templates_tool.installBusinessTemplateListFromRepository(
                            bt5_name_list, activate=True)

    for bt5_name in bt5_name_list:
      bt = self.templates_tool.getInstalledBusinessTemplate(bt5_name)
537
      self.assertEqual(bt, None)
538

539
    self.tic()
540 541 542
    for bt5_name in bt5_name_list:
      bt = self.templates_tool.getInstalledBusinessTemplate(bt5_name)
      self.assertNotEquals(bt, None)
543
      self.assertEqual(bt.getTitle(), bt5_name)
544 545

  def test_installBusinessTemplatesFromRepository_install_dependency(self):
546
    """Test if dependencies are automatically installed properly
547
    """
548 549
    # erp5_configurator_{ung,standard} depends on erp5_configurator which in
    # turn depends on erp5_workflow
550 551
    bt5_name_list = ['erp5_configurator_ung', 'erp5_configurator_standard']
    template_tool = self.portal.portal_templates
552 553 554
    for repos in template_tool.getRepositoryList():
      if "bootstrap" not in repos:
        repository = repos
555
    self.tic()
556 557
    for bt5_name in bt5_name_list:
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
558
      self.assertEqual(bt, None)
559 560

    bt = template_tool.getInstalledBusinessTemplate("erp5_configurator")
561
    self.assertEqual(bt, None)
562
    bt = template_tool.getInstalledBusinessTemplate("erp5_workflow")
563
    self.assertEqual(bt, None)
564 565 566 567 568 569 570 571 572 573 574 575

    self.assertRaises(BusinessTemplateMissingDependency,
              template_tool.installBusinessTemplateListFromRepository,
                            bt5_name_list)

    # Try fail in activities.
    self.assertRaises(BusinessTemplateMissingDependency,
              template_tool.installBusinessTemplateListFromRepository,
                      bt5_name_list, True, True, True)

    for bt5_name in bt5_name_list:
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
576
      self.assertEqual(bt, None)
577
      dependency_list = template_tool.getDependencyList(
578
                   (repository, bt5_name))
579 580 581 582 583 584 585
      self.assertNotEquals(dependency_list, [])

    template_tool.installBusinessTemplateListFromRepository(
                            bt5_name_list, install_dependency=True)
    for bt5_name in bt5_name_list:
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
      self.assertNotEquals(bt, None)
586 587 588 589 590

    bt = template_tool.getInstalledBusinessTemplate("erp5_configurator")
    self.assertNotEquals(bt, None)
    bt = template_tool.getInstalledBusinessTemplate("erp5_workflow")
    self.assertNotEquals(bt, None)
591
    self.abort()
592 593 594 595 596 597 598 599 600

    # Same as above but also check that dependencies are properly resolved if
    # one of the dependency is explicitly added to the list of bt5 to be
    # installed
    template_tool.installBusinessTemplateListFromRepository(
      bt5_name_list + ['erp5_workflow'],
      install_dependency=True)
    for bt5_name in bt5_name_list:
      bt = template_tool.getInstalledBusinessTemplate(bt5_name)
601 602
      self.assertNotEquals(bt, None)

603 604 605 606
    bt = template_tool.getInstalledBusinessTemplate("erp5_configurator")
    self.assertNotEquals(bt, None)
    bt = template_tool.getInstalledBusinessTemplate("erp5_workflow")
    self.assertNotEquals(bt, None)
607
    self.abort()
608

609 610 611 612 613
  def test_installBusinessTemplateListFromRepository_ignore_when_installed(self):
    """Check that install one business template, this method does not download
    many business templates that are already installed
    """
    template_tool = self.portal.portal_templates
614 615
    before = {bt.getTitle(): bt.getId()
      for bt in template_tool.getInstalledBusinessTemplateList()}
616 617
    bt_title = 'erp5_calendar'
    template_tool.installBusinessTemplateListFromRepository([bt_title],
618 619
        install_dependency=True)
    self.tic()
620 621
    after = {bt.getTitle(): bt.getId()
      for bt in template_tool.getInstalledBusinessTemplateList()}
622 623
    del after[bt_title]
    self.assertEqual(before, after)
624

625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
  def test_sortBusinessTemplateList(self):
    """Check sorting of a list of business template by their dependencies
    """
    template_tool = self.portal.portal_templates

    bt5list = template_tool.resolveBusinessTemplateListDependency(('erp5_credential',))
    # add some entropy by disorder bt5list returned by
    # resolveBusinessTemplateListDependency
    position_list = range(len(bt5list))
    new_bt5_list = []
    while position_list:
      position = random.choice(position_list)
      position_list.remove(position)
      new_bt5_list.append(bt5list[position])

    ordered_list = template_tool.sortBusinessTemplateList(new_bt5_list)
    # group orders
642 643 644
    first_group = range(0, 6)
    second_group =  range(6, 8)
    third_group = range(8, 10)
645 646
    fourth_group = range(10, 12)
    fifth_group = range(12, 13)
647

648 649 650 651 652
    expected_position_dict = {
      'erp5_property_sheets': first_group,
      'erp5_core_proxy_field_legacy': first_group,
      'erp5_mysql_innodb_catalog': first_group,
      'erp5_core': first_group,
653
      'erp5_full_text_mroonga_catalog': first_group,
654 655 656 657 658 659 660 661
      'erp5_xhtml_style': first_group,
      'erp5_ingestion_mysql_innodb_catalog': second_group,
      'erp5_base': second_group,
      'erp5_jquery': third_group,
      'erp5_ingestion': third_group,
      'erp5_web': fourth_group,
      'erp5_crm': fourth_group,
      'erp5_credential': fifth_group}
662

663 664
    for bt in ordered_list:
      self.assertTrue(ordered_list.index(bt) in expected_position_dict[bt[1]],
665
            'Expected positions for %r: %r, got %r' % (bt[1],
666 667 668
                                                  expected_position_dict[bt[1]],
                                                  ordered_list.index(bt)))

669 670 671 672
def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestTemplateTool))
  return suite