public void TestConsistencyOnExceptions()
        {
            // so the handler's index isn't empty
            replicator.Publish(CreateRevision(1));
            client.UpdateNow();
            client.Dispose();
            callback.Dispose();

            // Replicator violates write-once policy. It may be that the
            // handler copies files to the index dir, then fails to copy a
            // file and reverts the copy operation. On the next attempt, it
            // will copy the same file again. There is nothing wrong with this
            // in a real system, but it does violate write-once, and MDW
            // doesn't like it. Disabling it means that we won't catch cases
            // where the handler overwrites an existing index file, but
            // there's nothing currently we can do about it, unless we don't
            // use MDW.
            handlerIndexDir.PreventDoubleWrite = (false);
            handlerTaxoDir.PreventDoubleWrite  = (false);

            // wrap sourceDirFactory to return a MockDirWrapper so we can simulate errors
            ISourceDirectoryFactory @in      = sourceDirFactory;
            AtomicInt32             failures = new AtomicInt32(AtLeast(10));

            sourceDirFactory = new SourceDirectoryFactoryAnonymousInnerClass(this, @in, failures);
            handler          = new IndexAndTaxonomyReplicationHandler(handlerIndexDir, handlerTaxoDir, () =>
            {
                if (Random.NextDouble() < 0.2 && failures > 0)
                {
                    throw new Exception("random exception from callback");
                }
                return(null);
            });
            client = new ReplicationClientAnonymousInnerClass(this, replicator, handler, @in, failures);
            client.StartUpdateThread(10, "indexAndTaxo");

            Directory baseHandlerIndexDir = handlerIndexDir.Delegate;
            int       numRevisions        = AtLeast(20) + 2;

            for (int i = 2; i < numRevisions; i++)
            {
                replicator.Publish(CreateRevision(i));
                AssertHandlerRevision(i, baseHandlerIndexDir);
            }

            // disable errors -- maybe randomness didn't exhaust all allowed failures,
            // and we don't want e.g. CheckIndex to hit false errors.
            handlerIndexDir.MaxSizeInBytes              = (0);
            handlerIndexDir.RandomIOExceptionRate       = (0.0);
            handlerIndexDir.RandomIOExceptionRateOnOpen = (0.0);
            handlerTaxoDir.MaxSizeInBytes              = (0);
            handlerTaxoDir.RandomIOExceptionRate       = (0.0);
            handlerTaxoDir.RandomIOExceptionRateOnOpen = (0.0);
        }