FileDocCategorySizeDatePackage
AdapterHelperTest.javaAPI DocAndroid 5.1 API30589Thu Mar 12 22:22:56 GMT 2015android.support.v7.widget

AdapterHelperTest

public class AdapterHelperTest extends android.test.AndroidTestCase

Fields Summary
private static final boolean
DEBUG
private boolean
mCollectLogs
private static final String
TAG
List
mViewHolders
AdapterHelper
mAdapterHelper
List
mFirstPassUpdates
List
mSecondPassUpdates
TestAdapter
mTestAdapter
TestAdapter
mPreProcessClone
private List
mPreLayoutItems
private StringBuilder
mLog
Constructors Summary
Methods Summary
voidadd(int start, int count)

        if (DEBUG) {
            log("add(" + start + "," + count + ");");
        }
        mTestAdapter.add(start, count);
    
AdapterHelper.UpdateOpaddOp(int start, int count)

        return op(AdapterHelper.UpdateOp.ADD, start, count);
    
private voidaddViewHolder(int position)

        RecyclerViewBasicTest.MockViewHolder viewHolder = new RecyclerViewBasicTest.MockViewHolder(
                new TextView(getContext()));
        viewHolder.mPosition = position;
        viewHolder.mItem = mTestAdapter.mItems.get(position);
        mViewHolders.add(viewHolder);
    
private voidassertAdaptersEqual(android.support.v7.widget.AdapterHelperTest$TestAdapter a1, android.support.v7.widget.AdapterHelperTest$TestAdapter a2)

        assertEquals(a1.mItems.size(), a2.mItems.size());
        for (int i = 0; i < a1.mItems.size(); i++) {
            TestAdapter.Item item = a1.mItems.get(i);
            assertSame(item, a2.mItems.get(i));
            assertEquals(0, item.getUpdateCount());
        }
        assertEquals(0, a1.mPendingAdded.size());
        assertEquals(0, a2.mPendingAdded.size());
    
voidassertDispatch(int firstPass, int secondPass)

        assertEquals(firstPass, mFirstPassUpdates.size());
        assertEquals(secondPass, mSecondPassUpdates.size());
    
public voidassertOps(java.util.List actual, AdapterHelper.UpdateOp expected)

        assertEquals(expected.length, actual.size());
        for (int i = 0; i < expected.length; i++) {
            assertEquals(expected[i], actual.get(i));
        }
    
private voidcleanState()

        mLog.setLength(0);
        mPreLayoutItems = new ArrayList<TestAdapter.Item>();
        mViewHolders = new ArrayList<RecyclerViewBasicTest.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:" + updateOp.toString());
                }
                for (ViewHolder viewHolder : mViewHolders) {
                    for (int i = 0; i < updateOp.itemCount; i ++) {
                        // events are dispatched before view holders are updated for consistency
                        assertFalse("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);
    
booleanisItemLaidOut(int pos)

        for (ViewHolder viewHolder : mViewHolders) {
            if (viewHolder.mOldPosition == pos) {
                return true;
            }
        }
        return false;
    
voidlog(java.lang.String msg)

        if (mCollectLogs) {
            mLog.append(msg).append("\n");
        } else {
            Log.d(TAG, msg);
        }
    
private voidmv(int from, int to)

        if (DEBUG) {
            log("mv(" + from + "," + to + ");");
        }
        mTestAdapter.move(from, to);
    
intnextInt(java.util.Random random, int n)

        if (n == 0) {
            return 0;
        }
        return random.nextInt(n);
    
AdapterHelper.UpdateOpop(int cmd, int start, int count)

        return new AdapterHelper.UpdateOp(cmd, start, count);
    
voidpreProcess()

        for (RecyclerViewBasicTest.MockViewHolder vh : mViewHolders) {
            final int ind = mTestAdapter.mItems.indexOf(vh.mItem);
            assertEquals("actual adapter position should match", ind,
                    mAdapterHelper.applyPendingUpdatesToPosition(vh.mPosition));
        }
        mAdapterHelper.preProcess();
        for (int i = 0; i < mPreProcessClone.mItems.size(); i++) {
            TestAdapter.Item item = mPreProcessClone.mItems.get(i);
            final int preLayoutIndex = mPreLayoutItems.indexOf(item);
            final int endIndex = mTestAdapter.mItems.indexOf(item);
            if (preLayoutIndex != -1) {
                assertEquals("find position offset should work properly for existing elements" + i
                        + " at pre layout position " + preLayoutIndex + " and post layout position "
                        + endIndex, endIndex, mAdapterHelper.findPositionOffset(preLayoutIndex));
            }
        }
        // make sure visible view holders still have continuous positions
        final StringBuilder vhLogBuilder = new StringBuilder();
        for (ViewHolder vh : mViewHolders) {
            vhLogBuilder.append("\n").append(vh.toString());
        }
        if (mViewHolders.size() > 0) {
            final String vhLog = vhLogBuilder.toString();
            final int start = mViewHolders.get(0).getLayoutPosition();
            for (int i = 1; i < mViewHolders.size(); i++) {
                assertEquals("view holder positions should be continious in pre-layout" + vhLog,
                        start + i, mViewHolders.get(i).getLayoutPosition());
            }
        }
        mAdapterHelper.consumePostponedUpdates();
        // now assert these two adapters have identical data.
        mPreProcessClone.applyOps(mFirstPassUpdates, mTestAdapter);
        mPreProcessClone.applyOps(mSecondPassUpdates, mTestAdapter);
        assertAdaptersEqual(mTestAdapter, mPreProcessClone);
    
public voidrandomTest(java.util.Random random, int opCount)

        cleanState();
        if (DEBUG) {
            log("randomTest");
        }
        final int count = 10;// + nextInt(random,100);
        final int start = nextInt(random, count - 1);
        final int layoutCount = Math.max(1, nextInt(random, count - start));
        setupBasic(count, start, layoutCount);

        while (opCount-- > 0) {
            final int op = nextInt(random, 4);
            switch (op) {
                case 0:
                    if (mTestAdapter.mItems.size() > 1) {
                        int s = nextInt(random, mTestAdapter.mItems.size() - 1);
                        int len = Math.max(1, nextInt(random, mTestAdapter.mItems.size() - s));
                        rm(s, len);
                    }
                    break;
                case 1:
                    int s = mTestAdapter.mItems.size() == 0 ? 0 :
                            nextInt(random, mTestAdapter.mItems.size());
                        add(s, nextInt(random, 50));
                    break;
                case 2:
                    if (mTestAdapter.mItems.size() >= 2) {
                        int from = nextInt(random, mTestAdapter.mItems.size());
                        int to;
                        do {
                            to = nextInt(random, mTestAdapter.mItems.size());
                        } while (to == from);
                        mv(from, to);
                    }
                    break;
                case 3:
                    if (mTestAdapter.mItems.size() > 1) {
                        s = nextInt(random, mTestAdapter.mItems.size() - 1);
                        int len = Math.max(1, nextInt(random, mTestAdapter.mItems.size() - s));
                        up(s, len);
                    }
                    break;
            }
        }
        preProcess();
    
voidrm(int start, int count)

        if (DEBUG) {
            log("rm(" + start + "," + count + ");");
        }
        for (int i = start; i < start + count; i++) {
            if (!isItemLaidOut(i)) {
                TestAdapter.Item item = mTestAdapter.mItems.get(i);
                mPreLayoutItems.remove(item);
            }
        }
        mTestAdapter.remove(start, count);
    
AdapterHelper.UpdateOprmOp(int start, int count)

        return op(AdapterHelper.UpdateOp.REMOVE, start, count);
    
public voidrun(junit.framework.TestResult result)

        super.run(result);
        if (!result.wasSuccessful()) {
            result.addFailure(this, new AssertionFailedError(mLog.toString()));
        }
    
protected voidsetUp()


    
         
        cleanState();
    
voidsetupBasic(int count, int visibleStart, int visibleCount)

        if (DEBUG) {
            log("setupBasic(" + count + "," + visibleStart + "," + visibleCount + ");");
        }
        mTestAdapter = new TestAdapter(count, mAdapterHelper);
        for (int i = 0; i < visibleCount; i++) {
            addViewHolder(visibleStart + i);
        }
        mPreProcessClone = mTestAdapter.createCopy();
    
public voidtestAddCount()

        setupBasic(0, 0, 0);
        add(0, 1);
        assertEquals(1, mAdapterHelper.mPendingUpdates.size());
    
public voidtestAddProcess()

        setupBasic(0, 0, 0);
        add(0, 1);
        preProcess();
        assertEquals(0, mAdapterHelper.mPendingUpdates.size());
    
public voidtestAddRemoveSeparate()

        setupBasic(10, 2, 2);
        add(6, 1);
        rm(5, 1);
        preProcess();
        assertDispatch(1, 1);
    
public voidtestChangeAll()

        try {
            setupBasic(5, 0, 3);
            up(0, 5);
            mAdapterHelper.preProcess();
        } catch (Throwable t) {
            throw new Exception(mLog.toString());
        }
    
public voidtestDeleteCount()

        setupBasic(1, 0, 0);
        rm(0, 1);
        assertEquals(1, mAdapterHelper.mPendingUpdates.size());
    
public voidtestDeleteInvisible()

        setupBasic(10, 3, 4);
        rm(2, 1);
        preProcess();
        assertDispatch(1, 0);
    
public voidtestDeleteVisible()

        setupBasic(10, 2, 3);
        rm(2, 1);
        preProcess();
        assertDispatch(0, 1);
    
public voidtestDivideDelete()

        setupBasic(10, 3, 4);
        rm(2, 2);
        preProcess();
        assertDispatch(1, 1);
    
public voidtestFindPositionOffsetInPreLayout()

        setupBasic(50, 25, 10);
        rm(24, 5);
        mAdapterHelper.preProcess();
        // since 25 is invisible, we offset by one while checking
        assertEquals("find position for view 23",
                23, mAdapterHelper.findPositionOffset(23));
        assertEquals("find position for view 24",
                -1, mAdapterHelper.findPositionOffset(24));
        assertEquals("find position for view 25",
                -1, mAdapterHelper.findPositionOffset(25));
        assertEquals("find position for view 26",
                -1, mAdapterHelper.findPositionOffset(26));
        assertEquals("find position for view 27",
                -1, mAdapterHelper.findPositionOffset(27));
        assertEquals("find position for view 28",
                24, mAdapterHelper.findPositionOffset(28));
        assertEquals("find position for view 29",
                25, mAdapterHelper.findPositionOffset(29));
    
public voidtestMoveAdded()

        setupBasic(10, 2, 2);
        add(3, 5);
        mv(4, 2);
        preProcess();
    
public voidtestRandom()

        mCollectLogs = true;
        Random random = new Random(System.nanoTime());
        for (int i = 0; i < 100; i++) {
            try {
                Log.d(TAG, "running random test " + i);
                randomTest(random, Math.max(40, 10 + nextInt(random, i)));
            } catch (Throwable t) {
                throw new Throwable("failure at random test " + i + "\n" + t.getMessage()
                        + "\n" + mLog.toString(), t);
            }
        }
    
public voidtestScenario1()

        setupBasic(10, 3, 2);
        rm(4, 1);
        rm(3, 1);
        rm(3, 1);
        preProcess();
        assertDispatch(1, 2);
    
public voidtestScenario10()

        setupBasic(14, 10, 3);
        rm(4, 4);
        add(5, 11);
        mv(5, 18);
        rm(2, 9);
        preProcess();
    
public voidtestScenario11()

        setupBasic(78, 3, 64);
        mv(34, 28);
        add(1, 11);
        rm(9, 74);
        preProcess();
    
public voidtestScenario12()

        setupBasic(38, 9, 7);
        rm(26, 3);
        mv(29, 15);
        rm(30, 1);
        preProcess();
    
public voidtestScenario13()

        setupBasic(49, 41, 3);
        rm(30, 13);
        add(4, 10);
        mv(3, 38);
        mv(20, 17);
        rm(18, 23);
        preProcess();
    
public voidtestScenario14()

        setupBasic(24, 3, 11);
        rm(2, 15);
        mv(2, 1);
        add(2, 34);
        add(11, 3);
        rm(10, 25);
        rm(13, 6);
        rm(4, 4);
        rm(6, 4);
        preProcess();
    
public voidtestScenario15()

        setupBasic(10, 8, 1);
        mv(6, 1);
        mv(1, 4);
        rm(3, 1);
        preProcess();
    
public voidtestScenario16()

        setupBasic(10, 3, 3);
        rm(2, 1);
        rm(1, 7);
        rm(0, 1);
        preProcess();
    
public voidtestScenario17()

        setupBasic(10, 8, 1);
        mv(1, 0);
        mv(5, 1);
        rm(1, 7);
        preProcess();
    
public voidtestScenario18()

        setupBasic(10, 1, 4);
        add(2, 11);
        rm(16, 1);
        add(3, 1);
        rm(9, 10);
        preProcess();
    
public voidtestScenario19()

        setupBasic(10, 8, 1);
        mv(9, 7);
        mv(9, 3);
        rm(5,4);
        preProcess();
    
public voidtestScenario2()

        setupBasic(10, 3, 3); // 3-4-5
        add(4, 2); // 3 a b 4 5
        rm(0, 1); // (0) 3(2) a(3) b(4) 4(3) 5(4)
        rm(1, 3); // (1,2) (x) a(1) b(2) 4(3)
        preProcess();
        assertDispatch(2, 2);
    
public voidtestScenario20()

        setupBasic(10,7,1);
        mv(9,1);
        mv(3,9);
        rm(7,2);
        preProcess();
    
public voidtestScenario21()

        setupBasic(10,5,2);
        mv(1,0);
        mv(9,1);
        rm(2,3);
        preProcess();
    
public voidtestScenario22()

        setupBasic(10,7,2);
        add(2, 16);
        mv(20,9);
        rm(17,6);
        preProcess();
    
public voidtestScenario23()

        setupBasic(10,5,3);
        mv(9, 6);
        add(4, 15);
        rm(21,3);
        preProcess();
    
public voidtestScenario24()

        setupBasic(10,1,6);
        add(6, 5);
        mv(14, 6);
        rm(7,6);
        preProcess();
    
public voidtestScenario25()

        setupBasic(10,3,4);
        mv(3,9);
        rm(5,4);
        preProcess();
    
public voidtestScenario25a()

        setupBasic(10,3,4);
        rm(6,4);
        mv(3,5);
        preProcess();
    
public voidtestScenario26()

        setupBasic(10,4,4);
        rm(3,5);
        mv(2, 0);
        mv(1,0);
        rm(1, 1);
        mv(0, 2);
        preProcess();
    
public voidtestScenario27()

        setupBasic(10, 0, 3);
        mv(9,4);
        mv(8,4);
        add(7, 6);
        rm(5, 5);
        preProcess();
    
public voidtestScenario3()

        setupBasic(10, 2, 2);
        rm(0, 5);
        preProcess();
        assertDispatch(2, 1);
        assertOps(mFirstPassUpdates, rmOp(0, 2), rmOp(2, 1));
        assertOps(mSecondPassUpdates, rmOp(0, 2));
    
public voidtestScenario4()

        setupBasic(5, 0, 5);
        // 0 1 2 3 4
        // 0 1 2 a b 3 4
        // 0 2 a b 3 4
        // 0 c d 2 a b 3 4
        // 0 c d 2 a 4
        // c d 2 a 4
        // pre: 0 1 2 3 4
        add(3, 2);
        rm(1, 1);
        add(1, 2);
        rm(5, 2);
        rm(0, 1);
        preProcess();
    
public voidtestScenario5()

        setupBasic(5, 0, 5);
        // 0 1 2 3 4
        // 0 1 2 a b 3 4
        // 0 1 b 3 4
        // pre: 0 1 2 3 4
        // pre w/ adap: 0 1 2 b 3 4
        add(3, 2);
        rm(2, 2);
        preProcess();
    
public voidtestScenario6()

//        setupBasic(47, 19, 24);
//        mv(11, 12);
//        add(24, 16);
//        rm(9, 3);
        setupBasic(10, 5, 3);
        mv(2, 3);
        add(6, 4);
        rm(4, 1);
        preProcess();
    
public voidtestScenario8()

        setupBasic(68, 51, 13);
        mv(22, 11);
        mv(22, 52);
        rm(37, 19);
        add(12, 38);
        preProcess();
    
public voidtestScenario9()

        setupBasic(44, 3, 7);
        add(7, 21);
        rm(31, 3);
        rm(32, 11);
        mv(29, 5);
        mv(30, 32);
        add(25, 32);
        rm(15, 66);
        preProcess();
    
public voidtestScenerio28()

        setupBasic(10,4,1);
        mv(8, 6);
        rm(8, 1);
        mv(7,5);
        rm(3, 3);
        rm(1,4);
        preProcess();
    
public voidtestScenerio29()

        setupBasic(10, 6, 3);
        mv(3, 6);
        up(6,2);
        add(5, 5);
    
public voidtestScenerio30()

        mCollectLogs = true;
        setupBasic(10,3,1);
        rm(3,2);
        rm(2,5);
        preProcess();
    
public voidtestScenerio31()

        mCollectLogs = true;
        setupBasic(10,3,1);
        rm(3,1);
        rm(2,3);
        preProcess();
    
public voidtestScenerio32()

        setupBasic(10,8,1);
        add(9,2);
        add(7,39);
        up(0,39);
        mv(36,20);
        add(1,48);
        mv(22,98);
        mv(96,29);
        up(36,29);
        add(60,36);
        add(127,34);
        rm(142,22);
        up(12,69);
        up(116,13);
        up(118,19);
        mv(94,69);
        up(98,21);
        add(89,18);
        rm(94,70);
        up(71,8);
        rm(54,26);
        add(2,20);
        mv(78,84);
        mv(56,2);
        mv(1,79);
        rm(76,7);
        rm(57,12);
        rm(30,27);
        add(24,13);
        add(21,5);
        rm(11,27);
        rm(32,1);
        up(0,5);
        mv(14,9);
        rm(15,12);
        up(19,1);
        rm(7,1);
        mv(10,4);
        up(4,3);
        rm(16,1);
        up(13,5);
        up(2,8);
        add(10,19);
        add(15,42);
        preProcess();
    
public voidtestScenerio33()

        try {
            mCollectLogs = true;
            setupBasic(10, 7, 1);
            mv(0, 6);
            up(0, 7);
            preProcess();
        } catch (Throwable t) {
            throw new Throwable(t.getMessage() + "\n" + mLog.toString());
        }
    
public voidtestScenerio34()

        setupBasic(10,6,1);
        mv(9,7);
        rm(5,2);
        up(4,3);
        preProcess();
    
public voidtestScenerio35()

        setupBasic(10,4,4);
        mv(1,4);
        up(2,7);
        up(0,1);
        preProcess();
    
public voidtestScenerio36()

        setupBasic(10,7,2);
        rm(4,1);
        mv(1,6);
        up(4,4);
        preProcess();
    
public voidtestScenerio37()

        try {
            mCollectLogs = true;
            setupBasic(10, 5, 2);
            mv(3, 6);
            rm(4, 4);
            rm(3, 2);
            preProcess();
        } catch (Throwable t) {
            throw new Throwable(t.getMessage() + "\n" + mLog.toString());
        }
    
public voidtestScenerio38()

        setupBasic(10,2,2);
        add(0,24);
        rm(26,4);
        rm(1,24);
        preProcess();
    
public voidtestScenerio39()

        setupBasic(10,7,1);
        mv(0,2);
        rm(8,1);
        rm(2,6);
        preProcess();
    
public voidtestScenerio40()

        setupBasic(10,5,3);
        rm(5,4);
        mv(0,5);
        rm(2,3);
        preProcess();
    
public voidtestScenerio41()

        setupBasic(10,7,2);
        mv(4,9);
        rm(0,6);
        rm(0,1);
        preProcess();
    
public voidtestScenerio42()

        setupBasic(10,6,2);
        mv(5,9);
        rm(5,1);
        rm(2,6);
        preProcess();
    
public voidtestScenerio43()

        setupBasic(10,1,6);
        mv(6,8);
        rm(3,5);
        up(3, 1);
        preProcess();
    
public voidtestScenerio44()

        setupBasic(10,5,2);
        mv(6,4);
        mv(4,1);
        rm(5,3);
        preProcess();
    
public voidtestScenerio45()

        setupBasic(10,4,2);
        rm(1, 4);
        preProcess();
    
public voidtestScenerio46()

        setupBasic(10,4,3);
        up(6,1);
        mv(8,0);
        rm(2,7);
        preProcess();
    
public voidtestSinglePass()

        setupBasic(10, 2, 3);
        add(2, 1);
        rm(1, 2);
        add(1, 5);
        mAdapterHelper.consumeUpdatesInOnePass();
        assertDispatch(0, 3);
    
voidup(int start, int count)

        if (DEBUG) {
            log("up(" + start + "," + count + ");");
        }
        mTestAdapter.update(start, count);
    
AdapterHelper.UpdateOpupOp(int start, int count)

        return op(AdapterHelper.UpdateOp.UPDATE, start, count);
    
voidwaitForDebugger()

        android.os.Debug.waitForDebugger();