FileStorage-specific iterator tests
===================================

The FileStorage iterator has some special features that deserve some
special tests.

We'll make some assertions about time, so we'll take it over:

    >>> now = 1229959248
    >>> def faux_time():
    ...     global now
    ...     now += 0.1
    ...     return now
    >>> import time
    >>> time_time = time.time
    >>> time.time = faux_time

Commit a bunch of transactions:

    >>> import ZODB.FileStorage, transaction
    >>> db = ZODB.DB('data.fs')
    >>> tids = [db.storage.lastTransaction()]
    >>> poss = [db.storage._pos]
    >>> conn = db.open()
    >>> for i in range(100):
    ...     conn.root()[i] = conn.root().__class__()
    ...     transaction.commit()
    ...     tids.append(db.storage.lastTransaction())
    ...     poss.append(db.storage._pos)

Deciding where to start
-----------------------

By default, we start at the beginning:

    >>> it = ZODB.FileStorage.FileIterator('data.fs')
    >>> it.next().tid == tids[0]
    True

The file iterator has an optimization to deal with large files.  It
can serarch from either the front or the back of the file, depending
on the starting transaction given.  To see this, we'll turn on debug
logging:

    >>> import logging, sys
    >>> old_log_level = logging.getLogger().getEffectiveLevel()
    >>> logging.getLogger().setLevel(logging.DEBUG)
    >>> handler = logging.StreamHandler(sys.stdout)
    >>> logging.getLogger().addHandler(handler)

If we specify a start transaction, we'll scan forward or backward, as
seems best and set the next record to that:

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[0])
    >>> it.next().tid == tids[0]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[1])
    Scan forward data.fs:4 looking for '\x03z\xbd\xd8\xd06\x9c\xcc'
    >>> it.next().tid == tids[1]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[30])
    Scan forward data.fs:4 looking for '\x03z\xbd\xd8\xdc\x96.\xcc'
    >>> it.next().tid == tids[30]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[70])
    Scan backward data.fs:117080 looking for '\x03z\xbd\xd8\xed\xa7>\xcc'
    >>> it.next().tid == tids[70]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[-2])
    Scan backward data.fs:117080 looking for '\x03z\xbd\xd8\xfa\x06\xd0\xcc'
    >>> it.next().tid == tids[-2]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[-1])
    >>> it.next().tid == tids[-1]
    True

We can also supply a file position.  This can speed up finding the
starting point, or just pick up where another iterator left off:

    >>> it = ZODB.FileStorage.FileIterator('data.fs', pos=poss[50])
    >>> it.next().tid == tids[51]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[0], pos=4)
    >>> it.next().tid == tids[0]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[-1], pos=poss[-2])
    >>> it.next().tid == tids[-1]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[50], pos=poss[50])
    Scan backward data.fs:35936 looking for '\x03z\xbd\xd8\xe5\x1e\xb6\xcc'
    >>> it.next().tid == tids[50]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[49], pos=poss[50])
    Scan backward data.fs:35936 looking for '\x03z\xbd\xd8\xe4\xb1|\xcc'
    >>> it.next().tid == tids[49]
    True

    >>> it = ZODB.FileStorage.FileIterator('data.fs', tids[51], pos=poss[50])
    >>> it.next().tid == tids[51]
    True

    >>> logging.getLogger().setLevel(old_log_level)
    >>> logging.getLogger().removeHandler(handler)


If a starting transaction is before the first transaction in the file,
then the first transaction is returned.

    >>> from ZODB.utils import p64, u64
    >>> it = ZODB.FileStorage.FileIterator('data.fs', p64(u64(tids[0])-1))
    >>> it.next().tid == tids[0]
    True

If it is after the last transaction, then iteration be empty:

    >>> it = ZODB.FileStorage.FileIterator('data.fs', p64(u64(tids[-1])+1))
    >>> list(it)
    []

Even if we write more transactions:

    >>> it = ZODB.FileStorage.FileIterator('data.fs', p64(u64(tids[-1])+1))
    >>> for i in range(10):
    ...     conn.root()[i] = conn.root().__class__()
    ...     transaction.commit()
    >>> list(it)
    []

.. Cleanup

    >>> time.time = time_time
    >>> it.close()
    >>> db.close()
