1f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalpackage com.android.launcher3.model;
2f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
3f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport android.content.ContentValues;
4a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyalimport android.content.Context;
5f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport android.content.Intent;
6f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport android.database.Cursor;
7f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport android.graphics.Point;
8f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport android.test.ProviderTestCase2;
99345ebfc5c6e555938a153262fcd4243616183a6Hyunyoung Songimport android.test.suitebuilder.annotation.MediumTest;
10f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
11f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport com.android.launcher3.InvariantDeviceProfile;
12f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport com.android.launcher3.LauncherModel;
13f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport com.android.launcher3.LauncherSettings;
14803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyalimport com.android.launcher3.config.FeatureFlags;
15f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport com.android.launcher3.config.ProviderConfig;
16a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyalimport com.android.launcher3.model.GridSizeMigrationTask.MultiStepMigrationTask;
17f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport com.android.launcher3.util.TestLauncherProvider;
18f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
19f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport java.util.ArrayList;
20f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalimport java.util.HashSet;
21a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyalimport java.util.LinkedList;
22f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
23f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal/**
24f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal * Unit tests for {@link GridSizeMigrationTask}
25f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal */
269345ebfc5c6e555938a153262fcd4243616183a6Hyunyoung Song@MediumTest
27f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyalpublic class GridSizeMigrationTaskTest extends ProviderTestCase2<TestLauncherProvider> {
28f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
29f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private static final long DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
30f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private static final long HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
31f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
32f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private static final int APPLICATION = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
33f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
34f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
35f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private static final String TEST_PACKAGE = "com.android.launcher3.validpackage";
36f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private static final String VALID_INTENT =
37f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            new Intent(Intent.ACTION_MAIN).setPackage(TEST_PACKAGE).toUri(0);
38f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
39f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private HashSet<String> mValidPackages;
40f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private InvariantDeviceProfile mIdp;
41f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
42f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    public GridSizeMigrationTaskTest() {
43f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        super(TestLauncherProvider.class, ProviderConfig.AUTHORITY);
44f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
45f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
46f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    @Override
47f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    protected void setUp() throws Exception {
48f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        super.setUp();
49f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        mValidPackages = new HashSet<>();
50f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        mValidPackages.add(TEST_PACKAGE);
51f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
52f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        mIdp = new InvariantDeviceProfile();
53f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
54f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
55f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    public void testHotseatMigration_apps_dropped() throws Exception {
56f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long[] hotseatItems = {
57f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(APPLICATION, 0, HOTSEAT, 0, 0),
58f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(SHORTCUT, 1, HOTSEAT, 0, 0),
59f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                -1,
60f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
61f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(APPLICATION, 4, HOTSEAT, 0, 0),
62f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        };
63f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
64bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal        mIdp.numHotseatIcons = 3;
65bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, 5, 3)
66f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                .migrateHotseat();
67803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal        if (FeatureFlags.NO_ALL_APPS_ICON) {
68803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            // First item is dropped as it has the least weight.
69803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            verifyHotseat(hotseatItems[1], hotseatItems[3], hotseatItems[4]);
70803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal        } else {
71803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            // First & last items are dropped as they have the least weight.
72803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            verifyHotseat(hotseatItems[1], -1, hotseatItems[3]);
73803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal        }
74f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
75f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
76f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    public void testHotseatMigration_shortcuts_dropped() throws Exception {
77f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long[] hotseatItems = {
78f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(APPLICATION, 0, HOTSEAT, 0, 0),
79f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(30, 1, HOTSEAT, 0, 0),
80f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                -1,
81f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
82f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(10, 4, HOTSEAT, 0, 0),
83f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        };
84f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
85bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal        mIdp.numHotseatIcons = 3;
86bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, 5, 3)
87f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                .migrateHotseat();
88803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal        if (FeatureFlags.NO_ALL_APPS_ICON) {
89803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            // First item is dropped as it has the least weight.
90803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            verifyHotseat(hotseatItems[1], hotseatItems[3], hotseatItems[4]);
91803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal        } else {
92803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            // First & third items are dropped as they have the least weight.
93803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal            verifyHotseat(hotseatItems[1], -1, hotseatItems[4]);
94803896767b37e447bcdff7be6b9872612e93b7bfSunny Goyal        }
95f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
96f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
97f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private void verifyHotseat(long... sortedIds) {
98f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        int screenId = 0;
99f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        int total = 0;
100f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
101f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        for (long id : sortedIds) {
102f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
103f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    new String[]{LauncherSettings.Favorites._ID},
104f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    "container=-101 and screen=" + screenId, null, null, null);
105f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
106f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            if (id == -1) {
107f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                assertEquals(0, c.getCount());
108f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            } else {
109f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                assertEquals(1, c.getCount());
110f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                c.moveToNext();
111f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                assertEquals(id, c.getLong(0));
112f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                total ++;
113f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            }
114f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            c.close();
115f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
116f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            screenId++;
117f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }
118f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
119f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // Verify that not other entry exist in the DB.
120f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
121f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                new String[]{LauncherSettings.Favorites._ID},
122f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                "container=-101", null, null, null);
123f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        assertEquals(total, c.getCount());
124f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        c.close();
125f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
126f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
127f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    public void testWorkspace_empty_row_column_removed() throws Exception {
128f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long[][][] ids = createGrid(new int[][][]{{
129f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  0,  0, -1,  1},
130f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  3,  1, -1,  4},
131f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                { -1, -1, -1, -1},
132f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  5,  2, -1,  6},
133f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
134f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
135eb77aaea8990ede3ba774c7b92d48d098bda0f24Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages,
136f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
137f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
138f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // Column 2 and row 2 got removed.
139f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        verifyWorkspace(new long[][][] {{
140f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
141f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
142f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
143f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
144f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
145f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
146f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    public void testWorkspace_new_screen_created() throws Exception {
147f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long[][][] ids = createGrid(new int[][][]{{
148f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  0,  0,  0,  1},
149f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  3,  1,  0,  4},
150f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                { -1, -1, -1, -1},
151f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  5,  2, -1,  6},
152f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
153f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
154eb77aaea8990ede3ba774c7b92d48d098bda0f24Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages,
155f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
156f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
157f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // Items in the second column get moved to new screen
158f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        verifyWorkspace(new long[][][] {{
159f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
160f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
161f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
162f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }, {
163f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][0][2], ids[0][1][2], -1},
164f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
165f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
166f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
167f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    public void testWorkspace_items_merged_in_next_screen() throws Exception {
168f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long[][][] ids = createGrid(new int[][][]{{
169f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  0,  0,  0,  1},
170f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  3,  1,  0,  4},
171f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                { -1, -1, -1, -1},
172f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  5,  2, -1,  6},
173f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        },{
174f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  0,  0, -1,  1},
175f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  3,  1, -1,  4},
176f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
177f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
178eb77aaea8990ede3ba774c7b92d48d098bda0f24Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages,
179f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
180f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
181f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // Items in the second column of the first screen should get placed on the 3rd
182f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // row of the second screen
183f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        verifyWorkspace(new long[][][] {{
184f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
185f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
186f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
187f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }, {
188f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[1][0][0], ids[1][0][1], ids[1][0][3]},
189f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[1][1][0], ids[1][1][1], ids[1][1][3]},
190f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][0][2], ids[0][1][2], -1},
191f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
192f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
193f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
194f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    public void testWorkspace_items_not_merged_in_next_screen() throws Exception {
195f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // First screen has 2 items that need to be moved, but second screen has only one
196f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // empty space after migration (top-left corner)
197f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long[][][] ids = createGrid(new int[][][]{{
198f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  0,  0,  0,  1},
199f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  3,  1,  0,  4},
200f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                { -1, -1, -1, -1},
201f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  5,  2, -1,  6},
202f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        },{
203f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                { -1,  0, -1,  1},
204f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  3,  1, -1,  4},
205f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                { -1, -1, -1, -1},
206f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {  5,  2, -1,  6},
207f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
208f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
209eb77aaea8990ede3ba774c7b92d48d098bda0f24Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages,
210f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
211f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
212f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // Items in the second column of the first screen should get placed on a new screen.
213f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        verifyWorkspace(new long[][][] {{
214f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
215f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
216f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
217f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }, {
218f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {          -1, ids[1][0][1], ids[1][0][3]},
219f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[1][1][0], ids[1][1][1], ids[1][1][3]},
220f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[1][3][0], ids[1][3][1], ids[1][3][3]},
221f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }, {
222f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                {ids[0][0][2], ids[0][1][2], -1},
223f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }});
224f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
225f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
226da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal    public void testWorkspace_first_row_blocked() throws Exception {
227da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        // The first screen has one item on the 4th column which needs moving, as the first row
228da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        // will be kept empty.
229da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        long[][][] ids = createGrid(new int[][][]{{
230da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                { -1, -1, -1, -1},
231da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {  3,  1,  7,  0},
232da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {  8,  7,  7, -1},
233da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {  5,  2,  7, -1},
234da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        }}, 0);
235da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
236f03bd4f5470eed9808a0e6f345de94f4e578ae85Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages,
237da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                new Point(4, 4), new Point(3, 4)).migrateWorkspace();
238da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
239da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        // Items in the second column of the first screen should get placed on a new screen.
240da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        verifyWorkspace(new long[][][] {{
241da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {          -1,           -1,           -1},
242da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][1][0], ids[0][1][1], ids[0][1][2]},
243da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][2][0], ids[0][2][1], ids[0][2][2]},
244da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][3][0], ids[0][3][1], ids[0][3][2]},
245da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        }, {
246da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][1][3]},
247da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        }});
248da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal    }
249da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
250da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal    public void testWorkspace_items_moved_to_empty_first_row() throws Exception {
251da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        // Items will get moved to the next screen to keep the first screen empty.
252da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        long[][][] ids = createGrid(new int[][][]{{
253da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                { -1, -1, -1, -1},
254da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {  0,  1,  0,  0},
255da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {  8,  7,  7, -1},
256da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {  5,  6,  7, -1},
257da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        }}, 0);
258da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
259f03bd4f5470eed9808a0e6f345de94f4e578ae85Sunny Goyal        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages,
260da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
261da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
262da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        // Items in the second column of the first screen should get placed on a new screen.
263da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        verifyWorkspace(new long[][][] {{
264da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {          -1,           -1,           -1},
265da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][2][0], ids[0][2][1], ids[0][2][2]},
266da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][3][0], ids[0][3][1], ids[0][3][2]},
267da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        }, {
268da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][1][1], ids[0][1][0], ids[0][1][2]},
269da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                {ids[0][1][3]},
270da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        }});
271da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal    }
272da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
273da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal    private long[][][] createGrid(int[][][] typeArray) throws Exception {
274da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        return createGrid(typeArray, 1);
275da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal    }
276da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
277f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    /**
278f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     * Initializes the DB with dummy elements to represent the provided grid structure.
279f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     * @param typeArray A 3d array of item types. {@see #addItem(int, long, long, int, int)} for
280f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     *                  type definitions. The first dimension represents the screens and the next
281f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     *                  two represent the workspace grid.
282f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     * @return the same grid representation where each entry is the corresponding item id.
283f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     */
284da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal    private long[][][] createGrid(int[][][] typeArray, long startScreen) throws Exception {
285da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal        LauncherSettings.Settings.call(getMockContentResolver(),
286da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
287f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long[][][] ids = new long[typeArray.length][][];
288f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
289f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        for (int i = 0; i < typeArray.length; i++) {
290f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            // Add screen to DB
291da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal            long screenId = startScreen + i;
292da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal
293da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal            // Keep the screen id counter up to date
294da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal            LauncherSettings.Settings.call(getMockContentResolver(),
295da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                    LauncherSettings.Settings.METHOD_NEW_SCREEN_ID);
296f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
297f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            ContentValues v = new ContentValues();
298f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
299f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
300f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            getMockContentResolver().insert(LauncherSettings.WorkspaceScreens.CONTENT_URI, v);
301f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
302f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            ids[i] = new long[typeArray[i].length][];
303f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            for (int y = 0; y < typeArray[i].length; y++) {
304f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                ids[i][y] = new long[typeArray[i][y].length];
305f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                for (int x = 0; x < typeArray[i][y].length; x++) {
306f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    if (typeArray[i][y][x] < 0) {
307f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                        // Empty cell
308f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                        ids[i][y][x] = -1;
309f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    } else {
310f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                        ids[i][y][x] = addItem(typeArray[i][y][x], screenId, DESKTOP, x, y);
311f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    }
312f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                }
313f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            }
314f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }
315f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        return ids;
316f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
317f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
318f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    /**
319f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     * Verifies that the workspace items are arranged in the provided order.
320f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     * @param ids A 3d array where the first dimension represents the screen, and the rest two
321f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     *            represent the workspace grid.
322f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     */
323f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private void verifyWorkspace(long[][][] ids) {
324f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        ArrayList<Long> allScreens = LauncherModel.loadWorkspaceScreensDb(getMockContext());
325f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        assertEquals(ids.length, allScreens.size());
326f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        int total = 0;
327f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
328f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        for (int i = 0; i < ids.length; i++) {
329f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            long screenId = allScreens.get(i);
330f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            for (int y = 0; y < ids[i].length; y++) {
331f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                for (int x = 0; x < ids[i][y].length; x++) {
332f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    long id = ids[i][y][x];
333f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
334f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
335f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                            new String[]{LauncherSettings.Favorites._ID},
336f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                            "container=-100 and screen=" + screenId +
337f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                                    " and cellX=" + x + " and cellY=" + y, null, null, null);
338f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    if (id == -1) {
339f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                        assertEquals(0, c.getCount());
340f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    } else {
341f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                        assertEquals(1, c.getCount());
342f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                        c.moveToNext();
343a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                        assertEquals(String.format("Failed to verify item at %d %d, %d", i, y, x),
344da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                                id, c.getLong(0));
345f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                        total++;
346f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    }
347f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    c.close();
348f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                }
349f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            }
350f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }
351f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
352f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        // Verify that not other entry exist in the DB.
353f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
354f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                new String[]{LauncherSettings.Favorites._ID},
355f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                "container=-100", null, null, null);
356f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        assertEquals(total, c.getCount());
357f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        c.close();
358f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
359f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
360f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    /**
361f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     * Adds a dummy item in the DB.
362f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     * @param type {@link #APPLICATION} or {@link #SHORTCUT} or >= 2 for
363f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     *             folder (where the type represents the number of items in the folder).
364f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal     */
365f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    private long addItem(int type, long screen, long container, int x, int y) throws Exception {
366f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        long id = LauncherSettings.Settings.call(getMockContentResolver(),
367f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
368f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                .getLong(LauncherSettings.Settings.EXTRA_VALUE);
369f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
370f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        ContentValues values = new ContentValues();
371f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        values.put(LauncherSettings.Favorites._ID, id);
372f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        values.put(LauncherSettings.Favorites.CONTAINER, container);
373f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        values.put(LauncherSettings.Favorites.SCREEN, screen);
374f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        values.put(LauncherSettings.Favorites.CELLX, x);
375f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        values.put(LauncherSettings.Favorites.CELLY, y);
376f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        values.put(LauncherSettings.Favorites.SPANX, 1);
377f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        values.put(LauncherSettings.Favorites.SPANY, 1);
378f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
379f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        if (type == APPLICATION || type == SHORTCUT) {
380f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
381f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            values.put(LauncherSettings.Favorites.INTENT, VALID_INTENT);
382f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        } else {
383f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            values.put(LauncherSettings.Favorites.ITEM_TYPE,
384f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
385f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            // Add folder items.
386f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            for (int i = 0; i < type; i++) {
387f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                addItem(APPLICATION, 0, id, 0, 0);
388f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal            }
389f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        }
390f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal
391f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        getMockContentResolver().insert(LauncherSettings.Favorites.CONTENT_URI, values);
392f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal        return id;
393f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal    }
394a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
395a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    public void testMultiStepMigration_small_to_large() throws Exception {
396a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        MultiStepMigrationTaskVerifier verifier = new MultiStepMigrationTaskVerifier();
397a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        verifier.migrate(new Point(3, 3), new Point(5, 5));
398a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        verifier.assertCompleted();
399a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    }
400a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
401a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    public void testMultiStepMigration_large_to_small() throws Exception {
402a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        MultiStepMigrationTaskVerifier verifier = new MultiStepMigrationTaskVerifier(
403a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                5, 5, 4, 4,
404a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                4, 4, 3, 4
405a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        );
406a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        verifier.migrate(new Point(5, 5), new Point(3, 4));
407a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        verifier.assertCompleted();
408a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    }
409a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
410a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    public void testMultiStepMigration_zig_zag() throws Exception {
411a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        MultiStepMigrationTaskVerifier verifier = new MultiStepMigrationTaskVerifier(
412a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                5, 7, 4, 7,
413a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                4, 7, 3, 7
414a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        );
415a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        verifier.migrate(new Point(5, 5), new Point(3, 7));
416a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        verifier.assertCompleted();
417a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    }
418a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
419a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    private static class MultiStepMigrationTaskVerifier extends MultiStepMigrationTask {
420a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
421a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        private final LinkedList<Point> mPoints;
422a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
423a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        public MultiStepMigrationTaskVerifier(int... points) {
424a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            super(null, null);
425a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
426a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            mPoints = new LinkedList<>();
427a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            for (int i = 0; i < points.length; i += 2) {
428a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                mPoints.add(new Point(points[i], points[i + 1]));
429a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            }
430a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        }
431a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
432a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        @Override
433a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        protected boolean runStepTask(Point sourceSize, Point nextSize) throws Exception {
434a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            assertEquals(sourceSize, mPoints.poll());
435a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            assertEquals(nextSize, mPoints.poll());
436a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            return false;
437a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        }
438a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
439a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        public void assertCompleted() {
440a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            assertTrue(mPoints.isEmpty());
441a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal        }
442a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal    }
443f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal}
444