@Before
  public void cleanState() {
    mLog.setLength(0);
    mPreLayoutItems = new ArrayList<TestAdapter.Item>();
    mViewHolders = new ArrayList<MockViewHolder>();
    mFirstPassUpdates = new ArrayList<AdapterHelper.UpdateOp>();
    mSecondPassUpdates = new ArrayList<AdapterHelper.UpdateOp>();
    mPreProcessClone = null;
    mAdapterHelper =
        new AdapterHelper(
            new AdapterHelper.Callback() {
              @Override
              public RecyclerView.ViewHolder findViewHolder(int position) {
                for (ViewHolder vh : mViewHolders) {
                  if (vh.mPosition == position && !vh.isRemoved()) {
                    return vh;
                  }
                }
                return null;
              }

              @Override
              public void offsetPositionsForRemovingInvisible(int positionStart, int itemCount) {
                final int positionEnd = positionStart + itemCount;
                for (ViewHolder holder : mViewHolders) {
                  if (holder.mPosition >= positionEnd) {
                    holder.offsetPosition(-itemCount, true);
                  } else if (holder.mPosition >= positionStart) {
                    holder.flagRemovedAndOffsetPosition(positionStart - 1, -itemCount, true);
                  }
                }
              }

              @Override
              public void offsetPositionsForRemovingLaidOutOrNewView(
                  int positionStart, int itemCount) {
                final int positionEnd = positionStart + itemCount;
                for (ViewHolder holder : mViewHolders) {
                  if (holder.mPosition >= positionEnd) {
                    holder.offsetPosition(-itemCount, false);
                  } else if (holder.mPosition >= positionStart) {
                    holder.flagRemovedAndOffsetPosition(positionStart - 1, -itemCount, false);
                  }
                }
              }

              @Override
              public void markViewHoldersUpdated(int positionStart, int itemCount) {
                final int positionEnd = positionStart + itemCount;
                for (ViewHolder holder : mViewHolders) {
                  if (holder.mPosition >= positionStart && holder.mPosition < positionEnd) {
                    holder.addFlags(ViewHolder.FLAG_UPDATE);
                  }
                }
              }

              @Override
              public void onDispatchFirstPass(AdapterHelper.UpdateOp updateOp) {
                if (DEBUG) {
                  log("first pass:"******"update op should not match any existing view holders",
                        viewHolder.getLayoutPosition() == updateOp.positionStart + i);
                  }
                }

                mFirstPassUpdates.add(updateOp);
              }

              @Override
              public void onDispatchSecondPass(AdapterHelper.UpdateOp updateOp) {
                if (DEBUG) {
                  log("second pass:" + updateOp.toString());
                }
                mSecondPassUpdates.add(updateOp);
              }

              @Override
              public void offsetPositionsForAdd(int positionStart, int itemCount) {
                for (ViewHolder holder : mViewHolders) {
                  if (holder != null && holder.mPosition >= positionStart) {
                    holder.offsetPosition(itemCount, false);
                  }
                }
              }

              @Override
              public void offsetPositionsForMove(int from, int to) {
                final int start, end, inBetweenOffset;
                if (from < to) {
                  start = from;
                  end = to;
                  inBetweenOffset = -1;
                } else {
                  start = to;
                  end = from;
                  inBetweenOffset = 1;
                }
                for (ViewHolder holder : mViewHolders) {
                  if (holder == null || holder.mPosition < start || holder.mPosition > end) {
                    continue;
                  }
                  if (holder.mPosition == from) {
                    holder.offsetPosition(to - from, false);
                  } else {
                    holder.offsetPosition(inBetweenOffset, false);
                  }
                }
              }
            },
            true);
  }