Index: quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/base.py
===================================================================
--- quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/base.py	(revision 2841)
+++ quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/base.py	(revision 3002)
@@ -32,4 +32,6 @@
 from quintagroup.plonegooglesitemaps.interfaces import IGoogleSitemapsLayer
 
+from collective.testcaselayer.ptc import BasePTCLayer, ptc_layer
+
 quintagroup.plonegooglesitemaps.config.testing = 1
 quintagroup.plonegooglesitemaps.config.UPDATE_CATALOG = True
@@ -37,23 +39,40 @@
 PRODUCT = 'quintagroup.plonegooglesitemaps'
 
-@onsetup
-def setup_product():
-    """Set up the package and its dependencies.
 
-    The @onsetup decorator causes the execution of this body to be
-    deferred until the setup of the Plone site testing layer. We could
-    have created our own layer, but this is the easiest way for Plone
-    integration tests.
+class NotInstalled(BasePTCLayer):
+    """Initialize the package, without installation into portal
     """
-    fiveconfigure.debug_mode = True
-    import quintagroup.plonegooglesitemaps
-    zcml.load_config('configure.zcml', quintagroup.plonegooglesitemaps)
-    zcml.load_config('overrides.zcml', quintagroup.plonegooglesitemaps)
-    fiveconfigure.debug_mode = False
+    def afterSetUp(self):
+        fiveconfigure.debug_mode = True
+        import quintagroup.plonegooglesitemaps
+        zcml.load_config('configure.zcml', quintagroup.plonegooglesitemaps)
+        zcml.load_config('overrides.zcml', quintagroup.plonegooglesitemaps)
+        fiveconfigure.debug_mode = False
 
-    ztc.installPackage(PRODUCT)
+        if not ptc.PLONE31:
+            ztc.installProduct("plone.browserlayer")
 
-setup_product()
-ptc.setupPloneSite( products=(PRODUCT,))
+        ztc.installPackage(PRODUCT)
+
+
+class Installed(BasePTCLayer):
+    """ Install product into the portal
+    """
+    def afterSetUp(self):
+        if not ptc.PLONE31:
+            self.addProduct("plone.browserlayer")
+        self.addProduct(PRODUCT)
+
+class UnInstalled(BasePTCLayer):
+    """ UnInstall product from the portal
+    """
+    def afterSetUp(self):
+        qi = getattr(self.portal, 'portal_quickinstaller', None)
+        qi.uninstallProducts(products=[PRODUCT,])
+
+
+NotInstalledLayer = NotInstalled([ptc_layer,])
+InstalledLayer = Installed([NotInstalledLayer,])
+UnInstalledLayer = UnInstalled([InstalledLayer,])
 
 
@@ -67,6 +86,4 @@
         five's registerPackage directive not recognized on module initializing.
     """
-    layer = PloneSite
-
     def afterSetUp(self):
         self.loginAsPortalOwner()
@@ -81,17 +98,42 @@
 
     def beforeTearDown(self):
-        if self.orig_mobile_ifaces is not None:
+        if getattr(self, 'orig_mobile_ifaces', None) is not None:
             mobilesitemapview.MOBILE_INTERFACES = self.orig_mobile_ifaces
 
 
-class TestCase(MixinTestCase, ptc.PloneTestCase):
-    """ For unit tests """
+class TestCaseNotInstalled(ptc.PloneTestCase):
+    layer = NotInstalledLayer
+
+class TestCase(ptc.PloneTestCase, MixinTestCase):
+    layer = InstalledLayer
+
+    def afterSetUp(self):
+        ptc.PloneTestCase.afterSetUp(self)
+        MixinTestCase.afterSetUp(self)
+
+    def beforeTearDown(self):
+        ptc.PloneTestCase.beforeTearDown(self)
+        MixinTestCase.beforeTearDown(self)
 
 
-class FunctionalTestCase(MixinTestCase, ptc.FunctionalTestCase):
-    """ For functional tests """
+class TestCaseUnInstalled(ptc.PloneTestCase):
+    layer = UnInstalledLayer
+
+
+class FunctionalTestCaseNotInstalled(ptc.FunctionalTestCase):
+    layer = NotInstalledLayer
+
+class FunctionalTestCase(ptc.FunctionalTestCase, MixinTestCase):
+    layer = InstalledLayer
 
     def afterSetUp(self):
-        super(FunctionalTestCase, self).afterSetUp()
+        ptc.FunctionalTestCase.afterSetUp(self)
+        MixinTestCase.afterSetUp(self)
         self.auth = "%s:%s" % (portal_owner, default_password)
 
+    def beforeTearDown(self):
+        ptc.FunctionalTestCase.beforeTearDown(self)
+        MixinTestCase.beforeTearDown(self)
+
+class FunctionalTestCaseUnInstalled(ptc.FunctionalTestCase):
+    layer = UnInstalledLayer
Index: quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/testBlackoutList.py
===================================================================
--- quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/testBlackoutList.py	(revision 3002)
+++ quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/testBlackoutList.py	(revision 3002)
@@ -0,0 +1,153 @@
+#
+# Tests related to general Sitemap type.
+#
+from base import *
+from types import ListType, TupleType
+from zope import component
+from zope.component import queryMultiAdapter
+
+from Products.CMFPlone.utils import _createObjectByType
+from quintagroup.plonegooglesitemaps.interfaces import IBlackoutFilter
+
+
+class TestBOFilters(TestCase):
+
+    def testDefaultId(self):
+        idfilter = queryMultiAdapter((self.portal, self.app.REQUEST),
+                       IBlackoutFilter, name="id")
+        self.assertTrue(idfilter is not None,
+            "Not registered default 'id' IBlackoutFilter")
+
+    def testDefaultPath(self):
+        pathfilter = queryMultiAdapter((self.portal, self.app.REQUEST),
+                         IBlackoutFilter, name="path")
+        self.assertTrue(pathfilter is not None,
+            "Not registered default 'path' IBlackoutFilter")
+
+
+class TestFilterMixin(TestCase):
+
+    def afterSetUp(self):
+        super(TestFilterMixin, self).afterSetUp()
+        self.createTestContent()
+        self.sm = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
+        self.req = self.app.REQUEST
+        self.catres = self.portal.portal_catalog(portal_type=["Document",])
+        self.logout()
+
+    def createTestContent(self):
+        # Add testing content to portal
+        for cont in [self.portal, self.folder]:
+            for i in range(1,4):
+                doc = _createObjectByType('Document', cont, id='doc%i' % i)
+                doc.edit(text_format='plain', text='hello world %i' % i)
+                self.workflow.doActionFor(doc, 'publish')
+
+
+class TestDefaultFilters(TestFilterMixin):
+
+    def getPreparedLists(self, fname, fargs):
+        fengine = queryMultiAdapter((self.sm, self.req), IBlackoutFilter, name=fname)
+        filtered = [f.getPath() for f in fengine.filterOut(self.catres, fargs)]
+        catpaths = [c.getPath() for c in self.catres]
+        return catpaths, filtered
+
+    def testIdFilter(self):
+        catpaths, filtered = self.getPreparedLists("id", "doc1")
+        self.assertTrue(type(filtered) in [ListType, TupleType],
+            'Object type, returned by filteredOut method of "id" filter '\
+            'not list nor tuple')
+        excluded = ["/%s/doc1" % self.portal.absolute_url(1),
+                    "/%s/doc1" % self.folder.absolute_url(1)]
+        self.assertTrue(
+            set(catpaths)-set(filtered) == set(excluded),
+            'Wrong filtered-out by "id" filter:\nsrc %s\nres %s\nexcluded %s' % (
+             catpaths, filtered, excluded))
+
+    def testAbsolutePathFilter(self):
+        catpaths, filtered = self.getPreparedLists("path", "/doc1")
+        self.assertTrue(type(filtered) in [ListType, TupleType],
+            'Object type, returned by filteredOut method of "path" filter '\
+            'not list nor tuple')
+        excluded = ["/%s/doc1" % self.portal.absolute_url(1)]
+        self.assertTrue(
+            set(catpaths)-set(filtered) == set(excluded),
+            'Wrong filtered-out by "path" filter:\nsrc %s\nres %s\nexcluded %s' % (
+             catpaths, filtered, excluded))
+
+    def testRelativePathFilter(self):
+        self.sm = _createObjectByType('Sitemap', self.folder, id='google-sitemaps')
+        catpaths, filtered = self.getPreparedLists("path", "./doc1")
+        self.assertTrue(type(filtered) in [ListType, TupleType],
+            'Object type, returned by filteredOut method of "path" utility '\
+            'not list nor tuple')
+        excluded = ["/%s/doc1" % self.folder.absolute_url(1)]
+        self.assertTrue(
+            set(catpaths)-set(filtered) == set(excluded),
+            'Wrong filtered-out by "path" filter:\nsrc %s\nres %s\nexcluded %s' % (
+             catpaths, filtered, excluded))
+
+
+
+class TestBlacklistFormProcessing(TestFilterMixin):
+
+    def afterSetUp(self):
+        super(TestBlacklistFormProcessing, self).afterSetUp()
+        self.loginAsPortalOwner()
+        self.smview = queryMultiAdapter((self.sm, self.app.REQUEST), name="sitemap.xml")
+
+    def getPreparedLists(self, bl, fargs):
+        self.sm.edit(blackout_list=[bl,])
+        filtered = [f['url'] for f in self.smview.results()]
+        catpaths = [c.getURL() for c in self.catres]
+        return catpaths, filtered
+
+    def testGetNamedFilterUtility(self):
+        catpaths, filtered = self.getPreparedLists("path:/doc1", "/plone/doc1")
+        excluded = ["%s/doc1" % self.portal.absolute_url()]
+        self.assertTrue(set(catpaths)-set(filtered) == set(excluded),
+            'Wrong filtered-out by "id" filter:\nsrc %s\nres %s\nexcluded %s' % (
+             catpaths, filtered, excluded))
+
+    def testDefaultFilterUtility(self):
+        catpaths, filtered = self.getPreparedLists("id:doc1", "doc1")
+        excluded = ["%s/doc1" % self.portal.absolute_url(),
+                    "%s/doc1" % self.folder.absolute_url()]
+        self.assertTrue(set(catpaths)-set(filtered) == set(excluded),
+            'Wrong filtered-out by "id" filter:\nsrc %s\nres %s\nexcluded %s' % (
+             catpaths, filtered, excluded))
+        # Now check is output of unnamed filter samed to named one.
+        self.sm.edit(blackout_list=["doc1",])
+        filtered_dflt = [f['url'] for f in self.smview.results()]
+        map(lambda l: l.sort(), (filtered, filtered_dflt))
+        self.assertTrue(filtered == filtered_dflt,
+            'Output of named "id" filter is not same to unnamed one:\n' \
+            'id-named: %s\nunnamed: %s' % (filtered, filtered_dflt))
+
+    # def testGetCorrectFilterName(self):
+    #     call_names = []
+    #     origQMA = component._api.queryMultiAdapter
+    #     def patchQMA(objects, interface=Interface, name=u'', context=None):
+    #         call_names.append(name)
+    #         origQMA(objects, interface=interface, name=name, context=context)
+    #     component.queryMutliAdapter = patchQMA
+    #     self.sm.edit(blackout_list="FooFilterName:arg1:arg2:doc1")
+    #     self.smview.results()
+    #     self.assertTrue("FooFilterName" in call_names,
+    #         "Wrong filter name parsing - no FooFilterName in %s" % call_names)
+    #     component._api.queryMutliAdapter = origQMA
+        
+        
+        
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestBOFilters))
+    suite.addTest(makeSuite(TestDefaultFilters))
+    suite.addTest(makeSuite(TestBlacklistFormProcessing))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+#    framework()
Index: quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/testSitemaps.py
===================================================================
--- quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/testSitemaps.py	(revision 2841)
+++ quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/testSitemaps.py	(revision 3002)
@@ -76,4 +76,12 @@
         self.assertEqual(isinstance(wftrans, atapi.DisplayList), True)
         self.assertEqual("simple_publication_workflow#publish" in wftrans.keys(), True)
+
+    def testSettingBlackout(self):
+        bolist = ["path:./el1  ","   ",""," id:index.html  ","index_html"]
+        expect = ("path:./el1","id:index.html","index_html")
+        self.contentSM.edit(blackout_list=bolist)
+        value = self.contentSM.getBlackout_list()
+        self.assertTrue(value == expect, "Blackout list was not cleaned "\
+             "up from whitespaces: %s" % str(value))
 
 
Index: quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/test_doctest.py
===================================================================
--- quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/test_doctest.py	(revision 3002)
+++ quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/test_doctest.py	(revision 3002)
@@ -0,0 +1,31 @@
+import unittest
+import doctest
+
+from base import *
+from Products.CMFPlone.utils import _createObjectByType
+
+class DocTestCase(FunctionalTestCase):
+
+    def afterSetUp(self):
+        super(DocTestCase, self).afterSetUp()
+        #self.createTestContent()
+
+    def addDocument(self, cont, id, text):
+        doc = _createObjectByType('Document', cont, id=id)
+        doc.edit(text_format='plain', text=text)
+        self.workflow.doActionFor(doc, 'publish')
+        #return doc        
+
+def test_suite():
+    return unittest.TestSuite([
+
+        # Demonstrate the main content types
+        ztc.FunctionalDocFileSuite(
+            'filters.txt', package='quintagroup.plonegooglesitemaps',
+            test_class=DocTestCase, globs=globals(),
+            optionflags= doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),
+                       # | doctest.REPORT_ONLY_FIRST_FAILURE |
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
