14b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar/*
24b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * Copyright (C) 2014 The Android Open Source Project
34b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar *
44b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
54b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * you may not use this file except in compliance with the License.
64b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * You may obtain a copy of the License at
74b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar *
84b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
94b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar *
104b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * Unless required by applicable law or agreed to in writing, software
114b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
124b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * See the License for the specific language governing permissions and
144b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar * limitations under the License.
154b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar */
164b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
174b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarpackage android.support.v7.widget;
184b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
19be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyarimport org.junit.Before;
20be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyarimport org.junit.Test;
21be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyarimport org.junit.runner.RunWith;
22be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyarimport org.junit.runners.JUnit4;
234b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
244b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport java.util.ArrayList;
254b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport java.util.HashSet;
264b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport java.util.List;
274b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport java.util.Random;
284b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport java.util.Set;
294b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
304b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport android.support.v7.widget.AdapterHelper.UpdateOp;
314b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport android.util.Log;
324b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
334b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport static android.support.v7.widget.AdapterHelper.UpdateOp.ADD;
344b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport static android.support.v7.widget.AdapterHelper.UpdateOp.MOVE;
354b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport static android.support.v7.widget.AdapterHelper.UpdateOp.REMOVE;
364b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyarimport static android.support.v7.widget.AdapterHelper.UpdateOp.UPDATE;
37be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyarimport static org.junit.Assert.*;
384b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
39be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar@RunWith(JUnit4.class)
40be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyarpublic class OpReorderTest {
414b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
424b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private static final String TAG = "OpReorderTest";
434b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
444b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    List<UpdateOp> mUpdateOps = new ArrayList<UpdateOp>();
454b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    List<Item> mAddedItems = new ArrayList<Item>();
464b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    List<Item> mRemovedItems = new ArrayList<Item>();
474b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    Set<UpdateOp> mRecycledOps = new HashSet<UpdateOp>();
484b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    static Random random = new Random(System.nanoTime());
494b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
504b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    OpReorderer mOpReorderer = new OpReorderer(new OpReorderer.Callback() {
514b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        @Override
5221b345f101abc385496f42d250e580d21f1287b6Dake Gu        public UpdateOp obtainUpdateOp(int cmd, int startPosition, int itemCount, Object payload) {
5321b345f101abc385496f42d250e580d21f1287b6Dake Gu            return new UpdateOp(cmd, startPosition, itemCount, payload);
544b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
554b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
564b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        @Override
574b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        public void recycleUpdateOp(UpdateOp op) {
584b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            mRecycledOps.add(op);
594b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
604b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    });
614b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
624b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    int itemCount = 10;
634b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    int updatedItemCount = 0;
644b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
654b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void setup(int count) {
664b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        itemCount = count;
674b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        updatedItemCount = itemCount;
684b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
694b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
70be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Before
71be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    public void setUp() throws Exception {
724b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        cleanState();
734b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
744b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
754b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    void cleanState() {
764b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mUpdateOps = new ArrayList<UpdateOp>();
774b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mAddedItems = new ArrayList<Item>();
784b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mRemovedItems = new ArrayList<Item>();
794b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mRecycledOps = new HashSet<UpdateOp>();
804b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        Item.idCounter = 0;
814b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
824b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
83be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
844b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testMoveRemoved() throws Exception {
854b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(10);
864b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 8);
874b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(7, 3);
884b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
894b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
904b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
91be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
924b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testMoveRemove() throws Exception {
934b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(10);
944b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 8);
954b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 5);
964b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
974b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
984b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
99be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1004b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test1() {
1014b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(10);
1024b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 5);
1034b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 4);
1044b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1054b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1064b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
107be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1084b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test2() {
1094b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(5);
1104b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(1, 3);
1114b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(1, 1);
1124b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1134b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1144b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
115be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1164b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test3() {
1174b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(5);
1184b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(0, 4);
1194b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(2, 1);
1204b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1214b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1224b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
123be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1244b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test4() {
1254b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(5);
1264b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 0);
1274b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 1);
1284b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1294b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1304b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
131be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1324b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test5() {
1334b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(10);
1344b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(8, 1);
1354b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(6, 3);
1364b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1374b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1384b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
139be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1404b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test6() {
1414b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(5);
1424b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(1, 3);
1434b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(0, 3);
1444b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1454b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1464b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
147be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1484b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test7() {
1494b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(5);
1504b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 4);
1514b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 1);
1524b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1534b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1544b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
155be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1564b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test8() {
1574b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(5);
1584b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(4, 3);
1594b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 1);
1604b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1614b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1624b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
163be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1644b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void test9() {
1654b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        setup(5);
1664b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(2, 0);
1674b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(2, 2);
1684b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        process();
1694b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1704b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
171be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1724b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testRandom() throws Exception {
173670a72b9301fa53a763344036e4d3ff1995f36dfYigit Boyar        for (int i = 0; i < 150; i++) {
1744b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            try {
1754b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                cleanState();
1764b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                setup(50);
1774b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                for (int j = 0; j < 50; j++) {
1784b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    randOp(nextInt(random, nextInt(random, 4)));
1794b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                }
1804b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                Log.d(TAG, "running random test " + i);
1814b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                process();
1824b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            } catch (Throwable t) {
1834b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                throw new Exception(t.getMessage() + "\n" + opsToString(mUpdateOps));
1844b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            }
1854b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
1864b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
1874b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
188be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
1894b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testRandomMoveRemove() throws Exception {
190670a72b9301fa53a763344036e4d3ff1995f36dfYigit Boyar        for (int i = 0; i < 1000; i++) {
1914b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            try {
1924b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                cleanState();
1934b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                setup(5);
1944b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                orderedRandom(MOVE, REMOVE);
1954b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                process();
1964b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            } catch (Throwable t) {
1974b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                throw new Exception(t.getMessage() + "\n" + opsToString(mUpdateOps));
1984b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            }
1994b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
2004b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2014b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
202be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
2034b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testRandomMoveAdd() throws Exception {
204670a72b9301fa53a763344036e4d3ff1995f36dfYigit Boyar        for (int i = 0; i < 1000; i++) {
2054b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            try {
2064b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                cleanState();
2074b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                setup(5);
2084b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                orderedRandom(MOVE, ADD);
2094b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                process();
2104b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            } catch (Throwable t) {
2114b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                throw new Exception(t.getMessage() + "\n" + opsToString(mUpdateOps));
2124b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            }
2134b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
2144b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2154b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
216be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
2174b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testRandomMoveUpdate() throws Exception {
218670a72b9301fa53a763344036e4d3ff1995f36dfYigit Boyar        for (int i = 0; i < 1000; i++) {
2194b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            try {
2204b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                cleanState();
2214b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                setup(5);
2224b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                orderedRandom(MOVE, UPDATE);
2234b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                process();
2244b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            } catch (Throwable t) {
2254b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                throw new Exception(t.getMessage() + "\n" + opsToString(mUpdateOps));
2264b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            }
2274b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
2284b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2294b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2304b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private String opsToString(List<UpdateOp> updateOps) {
2314b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        StringBuilder sb = new StringBuilder();
2324b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (UpdateOp op : updateOps) {
2334b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            sb.append("\n").append(op.toString());
2344b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
2354b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        return sb.append("\n").toString();
2364b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2374b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2384b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void orderedRandom(int... ops) {
2394b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (int op : ops) {
2404b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            randOp(op);
2414b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
2424b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2434b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2444b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    void randOp(int cmd) {
2454b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        switch (cmd) {
2464b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            case REMOVE:
2474b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                if (updatedItemCount > 1) {
2484b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    int s = nextInt(random, updatedItemCount - 1);
2494b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    int len = Math.max(1, nextInt(random, updatedItemCount - s));
2504b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    rm(s, len);
2514b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                }
2524b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                break;
2534b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            case ADD:
2544b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                int s = updatedItemCount == 0 ? 0 : nextInt(random, updatedItemCount);
2554b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                add(s, nextInt(random, 50));
2564b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                break;
2574b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            case MOVE:
2584b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                if (updatedItemCount >= 2) {
2594b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    int from = nextInt(random, updatedItemCount);
2604b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    int to;
2614b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    do {
2624b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                        to = nextInt(random, updatedItemCount);
2634b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    } while (to == from);
2644b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    mv(from, to);
2654b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                }
2664b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                break;
2674b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            case UPDATE:
2684b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                if (updatedItemCount > 1) {
2694b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    s = nextInt(random, updatedItemCount - 1);
2704b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    int len = Math.max(1, nextInt(random, updatedItemCount - s));
2714b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    up(s, len);
2724b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                }
2734b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                break;
2744b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
2754b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2764b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2774b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    int nextInt(Random random, int n) {
2784b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        if (n == 0) {
2794b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            return 0;
2804b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
2814b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        return random.nextInt(n);
2824b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2834b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2844b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    UpdateOp rm(int start, int count) {
2854b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        updatedItemCount -= count;
28621b345f101abc385496f42d250e580d21f1287b6Dake Gu        return record(new UpdateOp(REMOVE, start, count, null));
2874b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2884b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2894b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    UpdateOp mv(int from, int to) {
29021b345f101abc385496f42d250e580d21f1287b6Dake Gu        return record(new UpdateOp(MOVE, from, to, null));
2914b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2924b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2934b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    UpdateOp add(int start, int count) {
2944b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        updatedItemCount += count;
29521b345f101abc385496f42d250e580d21f1287b6Dake Gu        return record(new UpdateOp(ADD, start, count, null));
2964b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
2974b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
2984b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    UpdateOp up(int start, int count) {
29921b345f101abc385496f42d250e580d21f1287b6Dake Gu        return record(new UpdateOp(UPDATE, start, count, null));
3004b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
3014b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3024b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    UpdateOp record(UpdateOp op) {
3034b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mUpdateOps.add(op);
3044b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        return op;
3054b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
3064b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3074b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    void process() {
3084b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        List<Item> items = new ArrayList<Item>(itemCount);
3094b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (int i = 0; i < itemCount; i++) {
3104b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            items.add(Item.create());
3114b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
3124b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        List<Item> clones = new ArrayList<Item>(itemCount);
3134b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (int i = 0; i < itemCount; i++) {
3144b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            clones.add(Item.clone(items.get(i)));
3154b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
3164b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        List<UpdateOp> rewritten = rewriteOps(mUpdateOps);
3174b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3184b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertAllMovesAtTheEnd(rewritten);
3194b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3204b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        apply(items, mUpdateOps);
3214b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        List<Item> originalAdded = mAddedItems;
3224b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        List<Item> originalRemoved = mRemovedItems;
3234b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        if (originalAdded.size() > 0) {
3244b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            Item.idCounter = originalAdded.get(0).id;
3254b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
3264b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mAddedItems = new ArrayList<Item>();
3274b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mRemovedItems = new ArrayList<Item>();
3284b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        apply(clones, rewritten);
3294b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3304b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        // now check equality
3314b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertListsIdentical(items, clones);
3324b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertHasTheSameItems(originalAdded, mAddedItems);
3334b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertHasTheSameItems(originalRemoved, mRemovedItems);
3344b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3354b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertRecycledOpsAreNotReused(items);
3364b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertRecycledOpsAreNotReused(clones);
3374b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
3384b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3394b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private void assertRecycledOpsAreNotReused(List<Item> items) {
3404b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (Item item : items) {
3414b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            assertFalse(mRecycledOps.contains(item));
3424b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
3434b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
3444b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3454b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private void assertAllMovesAtTheEnd(List<UpdateOp> ops) {
3464b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        boolean foundMove = false;
3474b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (UpdateOp op : ops) {
3484b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            if (op.cmd == MOVE) {
3494b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                foundMove = true;
3504b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            } else {
3514b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                assertFalse(foundMove);
3524b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            }
3534b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
3544b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
3554b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3564b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private void assertHasTheSameItems(List<Item> items,
3574b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            List<Item> clones) {
3584b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        String log = "has the same items\n" + toString(items) + "--\n" + toString(clones);
3594b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(log, items.size(), clones.size());
3604b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (Item item : items) {
3614b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            for (Item clone : clones) {
3624b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                if (item.id == clone.id && item.version == clone.version) {
3634b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    clones.remove(clone);
3644b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    break;
3654b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                }
3664b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            }
3674b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
3684b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(log, 0, clones.size());
3694b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
3704b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3714b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private void assertListsIdentical(List<Item> items, List<Item> clones) {
3724b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        String log = "is identical\n" + toString(items) + "--\n" + toString(clones);
3734b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(items.size(), clones.size());
3744b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (int i = 0; i < items.size(); i++) {
3754b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            Item.assertIdentical(log, items.get(i), clones.get(i));
3764b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
3774b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
3784b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
3794b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private void apply(List<Item> items, List<UpdateOp> updateOps) {
3804b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (UpdateOp op : updateOps) {
3814b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            switch (op.cmd) {
3824b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                case UpdateOp.ADD:
3834b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    for (int i = 0; i < op.itemCount; i++) {
3844b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                        final Item newItem = Item.create();
3854b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                        mAddedItems.add(newItem);
3864b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                        items.add(op.positionStart + i, newItem);
3874b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    }
3884b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    break;
3894b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                case UpdateOp.REMOVE:
3904b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    for (int i = 0; i < op.itemCount; i++) {
3914b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                        mRemovedItems.add(items.remove(op.positionStart));
3924b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    }
3934b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    break;
3944b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                case UpdateOp.MOVE:
3954b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    items.add(op.itemCount, items.remove(op.positionStart));
3964b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    break;
3974b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                case UpdateOp.UPDATE:
3984b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    for (int i = 0; i < op.itemCount; i++) {
3994b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                        final int index = op.positionStart + i;
4004b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                        items.get(index).version = items.get(index).version + 1;
4014b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    }
4024b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    break;
4034b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            }
4044b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
4054b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4064b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
4074b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private List<UpdateOp> rewriteOps(List<UpdateOp> updateOps) {
4084b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        List<UpdateOp> copy = new ArrayList<UpdateOp>();
4094b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (UpdateOp op : updateOps) {
41021b345f101abc385496f42d250e580d21f1287b6Dake Gu            copy.add(new UpdateOp(op.cmd, op.positionStart, op.itemCount, null));
4114b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
4124b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mOpReorderer.reorderOps(copy);
4134b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        return copy;
4144b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4154b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
416be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4174b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_1() {
4184b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(10, 15);
4194b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(2, 3);
4204b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4214b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
4224b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(7, 12), mUpdateOps.get(1));
4234b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(2, 3), mUpdateOps.get(0));
4244b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4254b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
426be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4274b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_2() {
4284b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 8);
4294b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(4, 2);
4304b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4314b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
4324b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(5, 2), mUpdateOps.get(0));
4334b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(3, 6), mUpdateOps.get(1));
4344b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4354b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
436be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4374b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_3() {
4384b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 8);
4394b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 2);
4404b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4414b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
4424b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(4, 2), mUpdateOps.get(0));
4434b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(3, 6), mUpdateOps.get(1));
4444b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4454b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
446be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4474b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_4() {
4484b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 8);
4494b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(2, 3);
4504b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4514b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(3, mUpdateOps.size());
4524b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(4, 2), mUpdateOps.get(0));
4534b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(2, 1), mUpdateOps.get(1));
4544b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(2, 5), mUpdateOps.get(2));
4554b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4564b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
457be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4584b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_5() {
4594b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 0);
4604b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(2, 3);
4614b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4624b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(3, mUpdateOps.size());
4634b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(4, 1), mUpdateOps.get(0));
4644b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(1, 2), mUpdateOps.get(1));
4654b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(1, 0), mUpdateOps.get(2));
4664b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4674b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
468be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4694b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_6() {
4704b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 10);
4714b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(2, 3);
4724b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4734b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(3, mUpdateOps.size());
4744b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(4, 2), mUpdateOps.get(0));
4754b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(2, 1), mUpdateOps.get(1));
4764b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4774b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
478be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4794b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_7() {
4804b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 2);
4814b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(6, 2);
4824b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4834b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
4844b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(6, 2), mUpdateOps.get(0));
4854b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(3, 2), mUpdateOps.get(1));
4864b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4874b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
488be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4894b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_8() {
4904b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 4);
4914b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 1);
4924b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
4934b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(1, mUpdateOps.size());
4944b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(4, 1), mUpdateOps.get(0));
4954b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
4964b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
497be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
4984b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_9() {
4994b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 4);
5004b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(4, 1);
5014b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5024b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(1, mUpdateOps.size());
5034b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(3, 1), mUpdateOps.get(0));
5044b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5054b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
506be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5074b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_10() {
5084b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(1, 3);
5094b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(0, 3);
5104b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5114b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
5124b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(2, 2), mUpdateOps.get(0));
5134b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(0, 1), mUpdateOps.get(1));
5144b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5154b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
516be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5174b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_11() {
5184b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(3, 8);
5194b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(7, 3);
5204b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5214b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
5224b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(3, 1), mUpdateOps.get(0));
5234b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(7, 2), mUpdateOps.get(1));
5244b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5254b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
526be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5274b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_12() {
5284b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(1, 3);
5294b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(2, 1);
5304b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5314b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
5324b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(3, 1), mUpdateOps.get(0));
5334b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(1, 2), mUpdateOps.get(1));
5344b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5354b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
536be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5374b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_13() {
5384b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(1, 3);
5394b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(1, 2);
5404b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5414b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(1, mUpdateOps.size());
5424b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(2, 2), mUpdateOps.get(1));
5434b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5444b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
545be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5464b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_14() {
5474b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(4, 2);
5484b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 1);
5494b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5504b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
5514b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(2, 1), mUpdateOps.get(0));
5524b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(2, 3), mUpdateOps.get(1));
5534b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5544b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
555be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5564b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_15() {
5574b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(4, 2);
5584b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(3, 2);
5594b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5604b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(1, mUpdateOps.size());
5614b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(2, 2), mUpdateOps.get(0));
5624b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5634b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
564be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5654b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveRemove_16() {
5664b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(2, 3);
5674b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        rm(1, 2);
5684b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveRemove(mUpdateOps, 0);
5694b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
5704b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(3, 1), mUpdateOps.get(0));
5714b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(rm(1, 1), mUpdateOps.get(1));
5724b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5734b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
574be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5754b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveUpdate_0() {
5764b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(1, 3);
5774b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        up(1, 2);
5784b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveUpdate(mUpdateOps, 0);
5794b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(2, mUpdateOps.size());
5804b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(up(2, 2), mUpdateOps.get(0));
5814b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(1, 3), mUpdateOps.get(1));
5824b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5834b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
584be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5854b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveUpdate_1() {
5864b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(0, 2);
5874b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        up(0, 4);
5884b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveUpdate(mUpdateOps, 0);
5894b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(3, mUpdateOps.size());
5904b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(up(0, 1), mUpdateOps.get(0));
5914b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(up(1, 3), mUpdateOps.get(1));
5924b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(0, 2), mUpdateOps.get(2));
5934b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
5944b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
595be7a54a6e02c9230a08e63f1c964907d129b6a10Yigit Boyar    @Test
5964b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    public void testSwapMoveUpdate_2() {
5974b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mv(2, 0);
5984b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        up(1, 3);
5994b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        swapMoveUpdate(mUpdateOps, 0);
6004b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(3, mUpdateOps.size());
6014b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(up(3, 1), mUpdateOps.get(0));
6024b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(up(0, 2), mUpdateOps.get(1));
6034b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        assertEquals(mv(2, 0), mUpdateOps.get(2));
6044b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
6054b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6064b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private void swapMoveUpdate(List<UpdateOp> list, int move) {
6074b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mOpReorderer.swapMoveUpdate(list, move, list.get(move), move + 1, list.get(move + 1));
6084b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
6094b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6104b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private void swapMoveRemove(List<UpdateOp> list, int move) {
6114b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        mOpReorderer.swapMoveRemove(list, move, list.get(move), move + 1, list.get(move + 1));
6124b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
6134b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6144b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    private String toString(List<Item> items) {
6154b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        StringBuilder sb = new StringBuilder();
6164b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        for (Item item : items) {
6174b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            sb.append(item.toString()).append("\n");
6184b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
6194b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        return sb.toString();
6204b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
6214b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6224b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    static class Item {
6234b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6244b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        static int idCounter = 0;
6254b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        int id;
6264b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        int version;
6274b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6284b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        Item(int id, int version) {
6294b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            this.id = id;
6304b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            this.version = version;
6314b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
6324b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6334b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        static Item create() {
6344b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            return new Item(idCounter++, 1);
6354b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
6364b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6374b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        static Item clone(Item other) {
6384b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            return new Item(other.id, other.version);
6394b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
6404b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6414b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        public static void assertIdentical(String logPrefix, Item item1, Item item2) {
6424b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            assertEquals(logPrefix + "\n" + item1 + " vs " + item2, item1.id, item2.id);
6434b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            assertEquals(logPrefix + "\n" + item1 + " vs " + item2, item1.version, item2.version);
6444b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
6454b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar
6464b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        @Override
6474b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        public String toString() {
6484b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar            return "Item{" +
6494b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    "id=" + id +
6504b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    ", version=" + version +
6514b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar                    '}';
6524b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar        }
6534b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar    }
6544b9b4d3fca81486051bac9aadb73d8865948c3bfYigit Boyar}
655