Ejemplo n.º 1
0
    def test_when_chunk_becomes_hidden_cached_data_is_cleared(self):
        """
        When a ``Chunk`` becomes hidden, then its cached data is deleted.
        """
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        keys = [c.display_key(kind) for kind in self.prepare_kinds]
        e = Entry()
        e.update(self.foo, "q", c, "foo", ChangeRecord.CREATE,
                 ChangeRecord.MANUAL)

        db = ExistDB()
        self.assertIsNotNone(cache.get(c.display_key("xml")))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)
        self.assertEqual(
            len(list_collection(db, self.display_collection_path)), 1)

        e.latest.hidden = True
        e.latest.save()

        for key in keys:
            self.assertIsNone(cache.get(key))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(
            len(list_collection(db, self.display_collection_path)), 0)
Ejemplo n.º 2
0
    def test_when_chunk_becomes_hidden_cached_data_is_cleared(self):
        """
        When a ``Chunk`` becomes hidden, then its cached data is deleted.
        """
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        keys = [c.display_key(kind) for kind in self.prepare_kinds]
        e = Entry()
        e.update(
            self.foo,
            "q",
            c,
            "foo",
            ChangeRecord.CREATE,
            ChangeRecord.MANUAL)

        db = ExistDB()
        self.assertIsNotNone(cache.get(c.display_key("xml")))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)
        self.assertEqual(len(list_collection(db,
                                             self.display_collection_path)),
                         1)

        e.latest.hidden = True
        e.latest.save()

        for key in keys:
            self.assertIsNone(cache.get(key))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(len(list_collection(db,
                                             self.display_collection_path)),
                         0)
Ejemplo n.º 3
0
    def check_abnormal_remove_data_from_exist_and_cache(self, op):
        db = ExistDB()
        c = Chunk(data="<div/>", is_normal=False)
        c.clean()
        cache.delete(c.c_hash)
        method = getattr(c, op)
        db.removeCollection(self.chunk_collection_path, True)
        db.removeCollection(self.display_collection_path, True)

        c.save()
        keys = [c.display_key(kind) for kind in self.prepare_kinds]

        for kind in self.prepare_kinds:
            self.assertIsNone(cache.get(c.display_key(kind)))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(len(list_collection(db,
                                             self.display_collection_path)),
                         0)

        with mock.patch('lexicography.models.ExistDB.removeDocument') as \
                remove_mock:
            method()
            self.assertEqual(remove_mock.call_count, 0)

        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(len(list_collection(db,
                                             self.display_collection_path)),
                         0)
        for key in keys:
            self.assertIsNone(cache.get(key))
Ejemplo n.º 4
0
    def check_abnormal_remove_data_from_exist_and_cache(self, op):
        db = ExistDB()
        c = Chunk(data="<div/>", is_normal=False)
        c.clean()
        cache.delete(c.c_hash)
        method = getattr(c, op)
        db.removeCollection(self.chunk_collection_path, True)
        db.removeCollection(self.display_collection_path, True)

        c.save()
        keys = [c.display_key(kind) for kind in self.prepare_kinds]

        for kind in self.prepare_kinds:
            self.assertIsNone(cache.get(c.display_key(kind)))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(
            len(list_collection(db, self.display_collection_path)), 0)

        with mock.patch('lexicography.models.ExistDB.removeDocument') as \
                remove_mock:
            method()
            self.assertEqual(remove_mock.call_count, 0)

        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(
            len(list_collection(db, self.display_collection_path)), 0)
        for key in keys:
            self.assertIsNone(cache.get(key))
Ejemplo n.º 5
0
    def check_deletes_documents(self, op, collection, *args):
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        entry = self.make_reachable(c)

        # If it does not have metadata yet, that's fine.
        try:
            c.chunkmetadata.delete()
        except ChunkMetadata.DoesNotExist:
            pass

        # We have to delete the collection because merely saving the
        # chunk causes it to be synced, but this is not what we are
        # testing here. We want to make sure that calling
        # op will perform the sync.
        db = ExistDB()
        db.removeCollection(collection, True)
        self.assertEqual(len(list_collection(db, collection)), 0)

        op = getattr(self.manager, op)
        op(*args)

        self.assertEqual(len(list_collection(db, collection)), 1)

        # Make sure our chunk was not collected.
        self.assertEqual(self.manager.count(), 1)

        # Now we delete the chunk in SQL because we do not want the
        # ``delete`` method to be called, as it would take care of
        # removing the document itself. (And yes, we do interpolate
        # the table name. This is safe as ``Entry._meta.db_table`` is
        # a value under our control.)
        with connection.cursor() as cursor:
            cr = entry.latest
            cursor.execute(
                "DELETE FROM {} WHERE id = %s".format(entry._meta.db_table),
                [entry.pk])
            # We have to do this ourselves because Django's cascading
            # delete is implemented at the ORM level, not the database
            # level.
            cursor.execute(
                "DELETE FROM {} WHERE id = %s".format(cr._meta.db_table),
                [cr.pk])

        # Check that no collection or syncing has occurred.
        self.assertEqual(self.manager.count(), 1)
        self.assertEqual(len(list_collection(db, collection)), 1)

        op(*args)

        # Make sure our chunk was collected.
        self.assertEqual(self.manager.count(), 0)
        self.assertEqual(len(list_collection(db, collection)), 0)
Ejemplo n.º 6
0
    def check_deletes_documents(self, op, collection, *args):
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        entry = self.make_reachable(c)

        # If it does not have metadata yet, that's fine.
        try:
            c.chunkmetadata.delete()
        except ChunkMetadata.DoesNotExist:
            pass

        # We have to delete the collection because merely saving the
        # chunk causes it to be synced, but this is not what we are
        # testing here. We want to make sure that calling
        # op will perform the sync.
        db = ExistDB()
        db.removeCollection(collection, True)
        self.assertEqual(len(list_collection(db, collection)), 0)

        op = getattr(self.manager, op)
        op(*args)

        self.assertEqual(len(list_collection(db, collection)), 1)

        # Make sure our chunk was not collected.
        self.assertEqual(self.manager.count(), 1)

        # Now we delete the chunk in SQL because we do not want the
        # ``delete`` method to be called, as it would take care of
        # removing the document itself. (And yes, we do interpolate
        # the table name. This is safe as ``Entry._meta.db_table`` is
        # a value under our control.)
        with connection.cursor() as cursor:
            cr = entry.latest
            cursor.execute(
                "DELETE FROM {} WHERE id = %s".format(entry._meta.db_table),
                [entry.pk])
            # We have to do this ourselves because Django's cascading
            # delete is implemented at the ORM level, not the database
            # level.
            cursor.execute(
                "DELETE FROM {} WHERE id = %s".format(cr._meta.db_table),
                [cr.pk])

        # Check that no collection or syncing has occurred.
        self.assertEqual(self.manager.count(), 1)
        self.assertEqual(len(list_collection(db, collection)), 1)

        op(*args)

        # Make sure our chunk was collected.
        self.assertEqual(self.manager.count(), 0)
        self.assertEqual(len(list_collection(db, collection)), 0)
Ejemplo n.º 7
0
    def check_skip_abnormal_chunks(self, op, collection, *args):
        c = Chunk(data="", is_normal=False)
        c.save()
        self.make_reachable(c)
        db = ExistDB()
        self.assertEqual(len(list_collection(db, collection)), 0)

        getattr(self.manager, op)(*args)

        self.assertEqual(len(list_collection(db, collection)), 0)

        # Make sure our chunk was not collected.
        self.assertEqual(self.manager.count(), 1)
Ejemplo n.º 8
0
    def check_skip_abnormal_chunks(self, op, collection, *args):
        c = Chunk(data="", is_normal=False)
        c.save()
        self.make_reachable(c)
        db = ExistDB()
        self.assertEqual(len(list_collection(db, collection)), 0)

        getattr(self.manager, op)(*args)

        self.assertEqual(len(list_collection(db, collection)), 0)

        # Make sure our chunk was not collected.
        self.assertEqual(self.manager.count(), 1)
Ejemplo n.º 9
0
    def check_skip_abnormal_chunks(self, op, collection, *args):
        c = Chunk(data="", is_normal=False)
        c.save()

        # We have to delete the collection because merely saving the
        # chunk causes it to be synced, but this is not what we are
        # testing here. We want to make sure that calling
        # sync_with_exist will perform the sync.
        db = ExistDB()
        db.removeCollection(collection, True)
        self.assertEqual(len(list_collection(db, collection)), 0)

        getattr(c, op)(*args)

        self.assertEqual(len(list_collection(db, collection)), 0)
Ejemplo n.º 10
0
    def check_skip_abnormal_chunks(self, op, collection, *args):
        c = Chunk(data="", is_normal=False)
        c.save()

        # We have to delete the collection because merely saving the
        # chunk causes it to be synced, but this is not what we are
        # testing here. We want to make sure that calling
        # sync_with_exist will perform the sync.
        db = ExistDB()
        db.removeCollection(collection, True)
        self.assertEqual(len(list_collection(db, collection)), 0)

        getattr(c, op)(*args)

        self.assertEqual(len(list_collection(db, collection)), 0)
Ejemplo n.º 11
0
    def test_sync_handles_overwrites(self):
        """
        ``sync_with_exist`` will not overwrite documents already in eXist.
        """
        db = ExistDB()
        db.removeCollection(self.chunk_collection_path, True)
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        c.sync_with_exist()

        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)

        with mock.patch('lexicography.models.ExistDB.load') as load_mock:
            c.sync_with_exist()
            self.assertEqual(load_mock.call_count, 0,
                             "load should not have been called!")

        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)
Ejemplo n.º 12
0
    def test_sync_handles_overwrites(self):
        """
        ``sync_with_exist`` will not overwrite documents already in eXist.
        """
        db = ExistDB()
        db.removeCollection(self.chunk_collection_path, True)
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        c.sync_with_exist()

        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)

        with mock.patch('lexicography.models.ExistDB.load') as load_mock:
            c.sync_with_exist()
            self.assertEqual(load_mock.call_count, 0,
                             "load should not have been called!")

        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)
Ejemplo n.º 13
0
    def check_syncs_normal_chunks(self, op, collection, *args):
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        self.make_reachable(c)
        # If it does not have metadata yet, that's fine.
        try:
            c.chunkmetadata.delete()
        except ChunkMetadata.DoesNotExist:
            pass

        # We have to delete the collection because merely saving the
        # chunk causes it to be synced, but this is not what we are
        # testing here. We want to make sure that calling
        # sync_with_exist will perform the sync.
        db = ExistDB()
        db.removeCollection(collection, True)
        self.assertEqual(len(list_collection(db, collection)), 0)

        getattr(self.manager, op)(*args)

        self.assertEqual(len(list_collection(db, collection)), 1)

        # Make sure our chunk was not collected.
        self.assertEqual(self.manager.count(), 1)
Ejemplo n.º 14
0
    def check_syncs_normal_chunks(self, op, collection, *args):
        c = Chunk(data="<div/>", is_normal=True)
        c.save()
        self.make_reachable(c)
        # If it does not have metadata yet, that's fine.
        try:
            c.chunkmetadata.delete()
        except ChunkMetadata.DoesNotExist:
            pass

        # We have to delete the collection because merely saving the
        # chunk causes it to be synced, but this is not what we are
        # testing here. We want to make sure that calling
        # sync_with_exist will perform the sync.
        db = ExistDB()
        db.removeCollection(collection, True)
        self.assertEqual(len(list_collection(db, collection)), 0)

        getattr(self.manager, op)(*args)

        self.assertEqual(len(list_collection(db, collection)), 1)

        # Make sure our chunk was not collected.
        self.assertEqual(self.manager.count(), 1)
Ejemplo n.º 15
0
    def check_remove_data_from_exist_and_cache(self, op):
        """
        Check that invoking ``op`` will remove the data from the eXist
        database and the cache.
        """
        db = ExistDB()
        c = Chunk(data="<div/>", is_normal=True)
        c.clean()
        method = op if callable(op) else getattr(c, op)
        cache.delete(c.c_hash)
        db.removeCollection(self.chunk_collection_path, True)
        db.removeCollection(self.display_collection_path, True)
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(len(list_collection(db,
                                             self.display_collection_path)),
                         0)

        for kind in self.prepare_kinds:
            self.assertIsNone(cache.get(c.display_key(kind)))

        c.save()
        c._create_cached_data()
        keys = [c.display_key(kind) for kind in self.prepare_kinds]

        # Only the "xml" data is created on save.
        self.assertIsNotNone(cache.get(c.display_key("xml")))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)
        self.assertEqual(len(list_collection(db,
                                             self.display_collection_path)),
                         1)

        method()
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(len(list_collection(db,
                                             self.display_collection_path)),
                         0)
        for key in keys:
            self.assertIsNone(cache.get(key))
Ejemplo n.º 16
0
    def check_remove_data_from_exist_and_cache(self, op):
        """
        Check that invoking ``op`` will remove the data from the eXist
        database and the cache.
        """
        db = ExistDB()
        c = Chunk(data="<div/>", is_normal=True)
        c.clean()
        method = op if isinstance(op, Callable) else getattr(c, op)
        cache.delete(c.c_hash)
        db.removeCollection(self.chunk_collection_path, True)
        db.removeCollection(self.display_collection_path, True)
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(
            len(list_collection(db, self.display_collection_path)), 0)

        for kind in self.prepare_kinds:
            self.assertIsNone(cache.get(c.display_key(kind)))

        c.save()
        c._create_cached_data()
        keys = [c.display_key(kind) for kind in self.prepare_kinds]

        # Only the "xml" data is created on save.
        self.assertIsNotNone(cache.get(c.display_key("xml")))
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         1)
        self.assertEqual(
            len(list_collection(db, self.display_collection_path)), 1)

        method()
        self.assertEqual(len(list_collection(db, self.chunk_collection_path)),
                         0)
        self.assertEqual(
            len(list_collection(db, self.display_collection_path)), 0)
        for key in keys:
            self.assertIsNone(cache.get(key))
Ejemplo n.º 17
0
 def _remove_absent(db, present, collection_path):
     for path in list_collection(db, collection_path):
         base = path.rsplit("/", 1)[-1]
         if base not in present:
             db.removeDocument(path, True)
Ejemplo n.º 18
0
 def list_display_collection(self):
     db = ExistDB()
     return list_collection(db, self.chunk_collection_path)
Ejemplo n.º 19
0
 def list_display_collection(self):
     db = ExistDB()
     return list_collection(db, self.chunk_collection_path)
Ejemplo n.º 20
0
 def _remove_absent(db, present, collection_path):
     for path in list_collection(db, collection_path):
         base = path.rsplit("/", 1)[-1]
         if base not in present:
             db.removeDocument(path, True)