##############################################################################
#
# Copyright (c) 2010 Zope Foundation 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.
#
##############################################################################
""" Unit tests for AcceleratedCacheManager module.
"""

import unittest

import transaction
import zope.component

from zope.component import testing as componenttesting
from zope.component import eventtesting

from AccessControl import SecurityManager
from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager
from OFS.tests.testCopySupport import CopySupportTestBase
from OFS.tests.testCopySupport import UnitTestSecurityPolicy
from OFS.tests.testCopySupport import UnitTestUser

from Zope2.App import zcml
from Products.StandardCacheManagers.RAMCacheManager import RAMCacheManager
from Products.StandardCacheManagers.AcceleratedHTTPCacheManager \
     import AcceleratedHTTPCacheManager
import Products.StandardCacheManagers

CACHE_META_TYPES = tuple(dict(name=instance_class.meta_type,
                              action='unused_constructor_name',
                              permission="Add %ss" % instance_class.meta_type)
                         for instance_class in (RAMCacheManager,
                                                AcceleratedHTTPCacheManager))


class CacheManagerLocationTests(CopySupportTestBase):

    _targetClass = None

    def _makeOne(self, *args, **kw):
        return self._targetClass(*args, **kw)

    def setUp(self):
        componenttesting.setUp()
        eventtesting.setUp()
        zcml.load_config('meta.zcml', zope.component)
        zcml.load_config('configure.zcml', Products.StandardCacheManagers)

        folder1, folder2 = self._initFolders()

        folder1.all_meta_types = folder2.all_meta_types = CACHE_META_TYPES

        self.folder1 = folder1
        self.folder2 = folder2

        self.policy = UnitTestSecurityPolicy()
        self.oldPolicy = SecurityManager.setSecurityPolicy(self.policy)

        cm_id = 'cache'
        manager = self._makeOne(cm_id)
        self.folder1._setObject(cm_id, manager)
        self.cachemanager = self.folder1[cm_id]
        transaction.savepoint(optimistic=True)

        newSecurityManager(None, UnitTestUser().__of__(self.root))

        CopySupportTestBase.setUp(self)

    def tearDown(self):

        noSecurityManager()
        SecurityManager.setSecurityPolicy(self.oldPolicy)
        del self.oldPolicy
        del self.policy
        del self.folder2
        del self.folder1

        self._cleanApp()
        componenttesting.tearDown()
        CopySupportTestBase.tearDown(self)

    def test_cache_differs_on_copy(self):
        # ensure copies don't hit the same cache
        cache = self.cachemanager.ZCacheManager_getCache()
        cachemanager_copy = self.folder2.manage_clone(self.cachemanager,
                                                      'cache_copy')
        cache_copy = cachemanager_copy.ZCacheManager_getCache()
        self.assertNotEqual(cache, cache_copy)

    def test_cache_remains_on_move(self):
        # test behaviour of cache on move.
        # NOTE: This test verifies current behaviour, but there is no actual
        # need for cache managers to maintain the same cache on move.
        # if physical path starts being used as a cache key, this test might
        # need to be fixed.
        cache = self.cachemanager.ZCacheManager_getCache()
        cut = self.folder1.manage_cutObjects(['cache'])
        self.folder2.manage_pasteObjects(cut)
        cachemanager_moved = self.folder2['cache']
        cache_moved = cachemanager_moved.ZCacheManager_getCache()
        self.assertEqual(cache, cache_moved)

    def test_cache_deleted_on_remove(self):
        old_cache = self.cachemanager.ZCacheManager_getCache()
        self.folder1.manage_delObjects(['cache'])
        new_cache = self.cachemanager.ZCacheManager_getCache()
        self.assertNotEqual(old_cache, new_cache)


class AcceleratedHTTPCacheManagerLocationTests(CacheManagerLocationTests):

    _targetClass = AcceleratedHTTPCacheManager


class RamCacheManagerLocationTests(CacheManagerLocationTests):

    _targetClass = RAMCacheManager


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(AcceleratedHTTPCacheManagerLocationTests))
    suite.addTest(unittest.makeSuite(RamCacheManagerLocationTests))
    return suite
