/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.pm.shortcutmanagertest;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.Callback;
import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.test.MoreAsserts;
import android.util.Log;

import junit.framework.Assert;

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * Common utility methods for ShortcutManager tests.  This is used by both CTS and the unit tests.
 * Because it's used by CTS too, it can only access the public APIs.
 */
public class ShortcutManagerTestUtils {
    private static final String TAG = "ShortcutManagerUtils";

    private static final boolean ENABLE_DUMPSYS = false; // DO NOT SUBMIT WITH true

    private static final int STANDARD_TIMEOUT_SEC = 5;

    private static final String[] EMPTY_STRINGS = new String[0];

    private ShortcutManagerTestUtils() {
    }

    public static List<String> readAll(File file) throws FileNotFoundException {
        return readAll(ParcelFileDescriptor.open(
                file.getAbsoluteFile(), ParcelFileDescriptor.MODE_READ_ONLY));
    }

    public static List<String> readAll(ParcelFileDescriptor pfd) {
        try {
            try {
                final ArrayList<String> ret = new ArrayList<>();
                try (BufferedReader r = new BufferedReader(
                        new FileReader(pfd.getFileDescriptor()))) {
                    String line;
                    while ((line = r.readLine()) != null) {
                        ret.add(line);
                    }
                    r.readLine();
                }
                return ret;
            } finally {
                pfd.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String concatResult(List<String> result) {
        final StringBuilder sb = new StringBuilder();
        for (String s : result) {
            sb.append(s);
            sb.append("\n");
        }
        return sb.toString();
    }

    public static boolean resultContains(List<String> result, String expected) {
        for (String line : result) {
            if (line.contains(expected)) {
                return true;
            }
        }
        return false;
    }

    public static List<String> assertSuccess(List<String> result) {
        if (!resultContains(result, "Success")) {
            fail("Command failed.  Result was:\n" + concatResult(result));
        }
        return result;
    }

    public static List<String> assertContains(List<String> result, String expected) {
        if (!resultContains(result, expected)) {
            fail("Didn't contain expected string=" + expected
                    + "\nActual:\n" + concatResult(result));
        }
        return result;
    }

    private static List<String> runCommand(Instrumentation instrumentation, String command) {
        return runCommand(instrumentation, command, null);
    }
    private static List<String> runCommand(Instrumentation instrumentation, String command,
            Predicate<List<String>> resultAsserter) {
        Log.d(TAG, "Running command: " + command);
        final List<String> result;
        try {
            result = readAll(
                    instrumentation.getUiAutomation().executeShellCommand(command));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (resultAsserter != null && !resultAsserter.test(result)) {
            fail("Command '" + command + "' failed, output was:\n" + concatResult(result));
        }
        return result;
    }

    private static void runCommandForNoOutput(Instrumentation instrumentation, String command) {
        runCommand(instrumentation, command, result -> result.size() == 0);
    }

    private static List<String> runShortcutCommand(Instrumentation instrumentation, String command,
            Predicate<List<String>> resultAsserter) {
        return runCommand(instrumentation, "cmd shortcut " + command, resultAsserter);
    }

    public static List<String> runShortcutCommandForSuccess(Instrumentation instrumentation,
            String command) {
        return runShortcutCommand(instrumentation, command, result -> result.contains("Success"));
    }

    public static String getDefaultLauncher(Instrumentation instrumentation) {
        final String PREFIX = "Launcher: ComponentInfo{";
        final String POSTFIX = "}";
        final List<String> result = runShortcutCommandForSuccess(
                instrumentation, "get-default-launcher");
        for (String s : result) {
            if (s.startsWith(PREFIX) && s.endsWith(POSTFIX)) {
                return s.substring(PREFIX.length(), s.length() - POSTFIX.length());
            }
        }
        fail("Default launcher not found");
        return null;
    }

    public static void setDefaultLauncher(Instrumentation instrumentation, String component) {
        runCommand(instrumentation, "cmd package set-home-activity " + component,
                result -> result.contains("Success"));
    }

    public static void setDefaultLauncher(Instrumentation instrumentation, Context packageContext) {
        setDefaultLauncher(instrumentation, packageContext.getPackageName()
                + "/android.content.pm.cts.shortcutmanager.packages.Launcher");
    }

    public static void overrideConfig(Instrumentation instrumentation, String config) {
        runShortcutCommandForSuccess(instrumentation, "override-config " + config);
    }

    public static void resetConfig(Instrumentation instrumentation) {
        runShortcutCommandForSuccess(instrumentation, "reset-config");
    }

    public static void resetThrottling(Instrumentation instrumentation) {
        runShortcutCommandForSuccess(instrumentation, "reset-throttling");
    }

    public static void resetAllThrottling(Instrumentation instrumentation) {
        runShortcutCommandForSuccess(instrumentation, "reset-all-throttling");
    }

    public static void clearShortcuts(Instrumentation instrumentation, int userId,
            String packageName) {
        runShortcutCommandForSuccess(instrumentation, "clear-shortcuts "
                + " --user " + userId + " " + packageName);
    }

    public static void dumpsysShortcut(Instrumentation instrumentation) {
        if (!ENABLE_DUMPSYS) {
            return;
        }
        Log.e(TAG, "Dumpsys shortcut");
        for (String s : runCommand(instrumentation, "dumpsys shortcut")) {
            Log.e(TAG, s);
        }
    }

    public static Bundle makeBundle(Object... keysAndValues) {
        assertTrue((keysAndValues.length % 2) == 0);

        if (keysAndValues.length == 0) {
            return null;
        }
        final Bundle ret = new Bundle();

        for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
            final String key = keysAndValues[i].toString();
            final Object value = keysAndValues[i + 1];

            if (value == null) {
                ret.putString(key, null);
            } else if (value instanceof Integer) {
                ret.putInt(key, (Integer) value);
            } else if (value instanceof String) {
                ret.putString(key, (String) value);
            } else if (value instanceof Bundle) {
                ret.putBundle(key, (Bundle) value);
            } else {
                fail("Type not supported yet: " + value.getClass().getName());
            }
        }
        return ret;
    }

    public static PersistableBundle makePersistableBundle(Object... keysAndValues) {
        assertTrue((keysAndValues.length % 2) == 0);

        if (keysAndValues.length == 0) {
            return null;
        }
        final PersistableBundle ret = new PersistableBundle();

        for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
            final String key = keysAndValues[i].toString();
            final Object value = keysAndValues[i + 1];

            if (value == null) {
                ret.putString(key, null);
            } else if (value instanceof Integer) {
                ret.putInt(key, (Integer) value);
            } else if (value instanceof String) {
                ret.putString(key, (String) value);
            } else if (value instanceof PersistableBundle) {
                ret.putPersistableBundle(key, (PersistableBundle) value);
            } else {
                fail("Type not supported yet: " + value.getClass().getName());
            }
        }
        return ret;
    }

    public static <T> List<T> list(T... array) {
        return Arrays.asList(array);
    }

    public static <T> Set<T> hashSet(Set<T> in) {
        return new LinkedHashSet<>(in);
    }

    public static <T> Set<T> set(T... values) {
        return set(v -> v, values);
    }

    public static <T, V> Set<T> set(Function<V, T> converter, V... values) {
        return set(converter, Arrays.asList(values));
    }

    public static <T, V> Set<T> set(Function<V, T> converter, List<V> values) {
        final LinkedHashSet<T> ret = new LinkedHashSet<>();
        for (V v : values) {
            ret.add(converter.apply(v));
        }
        return ret;
    }

    public static void resetAll(Collection<?> mocks) {
        for (Object o : mocks) {
            reset(o);
        }
    }

    public static <T extends Collection<?>> T assertEmpty(T collection) {
        if (collection == null) {
            return collection; // okay.
        }
        assertEquals(0, collection.size());
        return collection;
    }

    public static List<ShortcutInfo> filter(List<ShortcutInfo> list, Predicate<ShortcutInfo> p) {
        final ArrayList<ShortcutInfo> ret = new ArrayList<>(list);
        ret.removeIf(si -> !p.test(si));
        return ret;
    }

    public static List<ShortcutInfo> filterByActivity(List<ShortcutInfo> list,
            ComponentName activity) {
        return filter(list, si ->
                (si.getActivity().equals(activity)
                        && (si.isDeclaredInManifest() || si.isDynamic())));
    }

    public static List<ShortcutInfo> changedSince(List<ShortcutInfo> list, long time) {
        return filter(list, si -> si.getLastChangedTimestamp() >= time);
    }

    @FunctionalInterface
    public interface ExceptionRunnable {
        void run() throws Exception;
    }

    public static void assertExpectException(Class<? extends Throwable> expectedExceptionType,
            String expectedExceptionMessageRegex, ExceptionRunnable r) {
        assertExpectException("", expectedExceptionType, expectedExceptionMessageRegex, r);
    }

    public static void assertCannotUpdateImmutable(Runnable r) {
        assertExpectException(
                IllegalArgumentException.class, "may not be manipulated via APIs", r::run);
    }

    public static void assertDynamicShortcutCountExceeded(Runnable r) {
        assertExpectException(IllegalArgumentException.class,
                "Max number of dynamic shortcuts exceeded", r::run);
    }

    public static void assertExpectException(String message,
            Class<? extends Throwable> expectedExceptionType,
            String expectedExceptionMessageRegex, ExceptionRunnable r) {
        try {
            r.run();
        } catch (Throwable e) {
            Assert.assertTrue(
                    "Expected exception type was " + expectedExceptionType.getName()
                            + " but caught " + e + " (message=" + message + ")",
                    expectedExceptionType.isAssignableFrom(e.getClass()));
            if (expectedExceptionMessageRegex != null) {
                MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
            }
            return; // Pass
        }
        Assert.fail("Expected exception type " + expectedExceptionType.getName()
                + " was not thrown");
    }

    public static List<ShortcutInfo> assertShortcutIds(List<ShortcutInfo> actualShortcuts,
            String... expectedIds) {
        final SortedSet<String> expected = new TreeSet<>(list(expectedIds));
        final SortedSet<String> actual = new TreeSet<>();
        for (ShortcutInfo s : actualShortcuts) {
            actual.add(s.getId());
        }

        // Compare the sets.
        assertEquals(expected, actual);
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertShortcutIdsOrdered(List<ShortcutInfo> actualShortcuts,
            String... expectedIds) {
        final ArrayList<String> expected = new ArrayList<>(list(expectedIds));
        final ArrayList<String> actual = new ArrayList<>();
        for (ShortcutInfo s : actualShortcuts) {
            actual.add(s.getId());
        }
        assertEquals(expected, actual);
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllHaveIntents(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertNotNull("ID " + s.getId(), s.getIntent());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllNotHaveIntents(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertNull("ID " + s.getId(), s.getIntent());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllHaveTitle(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertNotNull("ID " + s.getId(), s.getShortLabel());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllNotHaveTitle(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertNull("ID " + s.getId(), s.getShortLabel());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllKeyFieldsOnly(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), s.hasKeyFieldsOnly());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllNotKeyFieldsOnly(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertFalse("ID " + s.getId(), s.hasKeyFieldsOnly());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllDynamic(List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), s.isDynamic());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), s.isPinned());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllDynamicOrPinned(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), s.isDynamic() || s.isPinned());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllManifest(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), s.isDeclaredInManifest());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllNotManifest(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertFalse("ID " + s.getId(), s.isDeclaredInManifest());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllDisabled(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), !s.isEnabled());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllEnabled(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), s.isEnabled());
        }
        return actualShortcuts;
    }

    public static List<ShortcutInfo> assertAllImmutable(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId(), s.isImmutable());
        }
        return actualShortcuts;
    }

    public static void assertDynamicOnly(ShortcutInfo si) {
        assertTrue(si.isDynamic());
        assertFalse(si.isPinned());
    }

    public static void assertPinnedOnly(ShortcutInfo si) {
        assertFalse(si.isDynamic());
        assertFalse(si.isDeclaredInManifest());
        assertTrue(si.isPinned());
    }

    public static void assertDynamicAndPinned(ShortcutInfo si) {
        assertTrue(si.isDynamic());
        assertTrue(si.isPinned());
    }

    public static void assertBitmapSize(int expectedWidth, int expectedHeight, Bitmap bitmap) {
        assertEquals("width", expectedWidth, bitmap.getWidth());
        assertEquals("height", expectedHeight, bitmap.getHeight());
    }

    public static <T> void assertAllUnique(Collection<T> list) {
        final Set<Object> set = new LinkedHashSet<>();
        for (T item : list) {
            if (set.contains(item)) {
                fail("Duplicate item found: " + item + " (in the list: " + list + ")");
            }
            set.add(item);
        }
    }

    public static ShortcutInfo findShortcut(List<ShortcutInfo> list, String id) {
        for (ShortcutInfo si : list) {
            if (si.getId().equals(id)) {
                return si;
            }
        }
        fail("Shortcut " + id + " not found in the list");
        return null;
    }

    public static Bitmap pfdToBitmap(ParcelFileDescriptor pfd) {
        assertNotNull(pfd);
        try {
            try {
                return BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
            } finally {
                pfd.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void assertBundleEmpty(BaseBundle b) {
        assertTrue(b == null || b.size() == 0);
    }

    public static void assertCallbackNotReceived(LauncherApps.Callback mock) {
        verify(mock, times(0)).onShortcutsChanged(anyString(), anyList(),
                any(UserHandle.class));
    }

    public static void assertCallbackReceived(LauncherApps.Callback mock,
            UserHandle user, String packageName, String... ids) {
        verify(mock).onShortcutsChanged(eq(packageName), checkShortcutIds(ids),
                eq(user));
    }

    public static boolean checkAssertSuccess(Runnable r) {
        try {
            r.run();
            return true;
        } catch (AssertionError e) {
            return false;
        }
    }

    public static <T> T checkArgument(Predicate<T> checker, String description,
            List<T> matchedCaptor) {
        final Matcher<T> m = new BaseMatcher<T>() {
            @Override
            public boolean matches(Object item) {
                if (item == null) {
                    return false;
                }
                final T value = (T) item;
                if (!checker.test(value)) {
                    return false;
                }

                if (matchedCaptor != null) {
                    matchedCaptor.add(value);
                }
                return true;
            }

            @Override
            public void describeTo(Description d) {
                d.appendText(description);
            }
        };
        return Mockito.argThat(m);
    }

    public static List<ShortcutInfo> checkShortcutIds(String... ids) {
        return checkArgument((List<ShortcutInfo> list) -> {
            final Set<String> actualSet = set(si -> si.getId(), list);
            return actualSet.equals(set(ids));

        }, "Shortcut IDs=[" + Arrays.toString(ids) + "]", null);
    }

    public static ShortcutInfo parceled(ShortcutInfo si) {
        Parcel p = Parcel.obtain();
        p.writeParcelable(si, 0);
        p.setDataPosition(0);
        ShortcutInfo si2 = p.readParcelable(ShortcutManagerTestUtils.class.getClassLoader());
        p.recycle();
        return si2;
    }

    public static List<ShortcutInfo> cloneShortcutList(List<ShortcutInfo> list) {
        if (list == null) {
            return null;
        }
        final List<ShortcutInfo> ret = new ArrayList<>(list.size());
        for (ShortcutInfo si : list) {
            ret.add(parceled(si));
        }

        return ret;
    }

    private static final Comparator<ShortcutInfo> sRankComparator =
            (ShortcutInfo a, ShortcutInfo b) -> Integer.compare(a.getRank(), b.getRank());

    public static List<ShortcutInfo> sortedByRank(List<ShortcutInfo> shortcuts) {
        final ArrayList<ShortcutInfo> ret = new ArrayList<>(shortcuts);
        Collections.sort(ret, sRankComparator);
        return ret;
    }

    public static void waitUntil(String message, BooleanSupplier condition) {
        waitUntil(message, condition, STANDARD_TIMEOUT_SEC);
    }

    public static void waitUntil(String message, BooleanSupplier condition, int timeoutSeconds) {
        final long timeout = System.currentTimeMillis() + (timeoutSeconds * 1000L);
        while (System.currentTimeMillis() < timeout) {
            if (condition.getAsBoolean()) {
                return;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        fail("Timed out for: " + message);
    }

    public static ShortcutListAsserter assertWith(List<ShortcutInfo> list) {
        return new ShortcutListAsserter(list);
    }

    /**
     * New style assertion that allows chained calls.
     */
    public static class ShortcutListAsserter {
        private final ShortcutListAsserter mOriginal;
        private final List<ShortcutInfo> mList;

        ShortcutListAsserter(List<ShortcutInfo> list) {
            this(null, list);
        }

        private ShortcutListAsserter(ShortcutListAsserter original, List<ShortcutInfo> list) {
            mOriginal = (original == null) ? this : original;
            mList = (list == null) ? new ArrayList<>(0) : new ArrayList<>(list);
        }

        public ShortcutListAsserter revertToOriginalList() {
            return mOriginal;
        }

        public ShortcutListAsserter selectDynamic() {
            return new ShortcutListAsserter(this,
                    filter(mList, ShortcutInfo::isDynamic));
        }

        public ShortcutListAsserter selectManifest() {
            return new ShortcutListAsserter(this,
                    filter(mList, ShortcutInfo::isDeclaredInManifest));
        }

        public ShortcutListAsserter selectPinned() {
            return new ShortcutListAsserter(this,
                    filter(mList, ShortcutInfo::isPinned));
        }

        public ShortcutListAsserter selectByActivity(ComponentName activity) {
            return new ShortcutListAsserter(this,
                    ShortcutManagerTestUtils.filterByActivity(mList, activity));
        }

        public ShortcutListAsserter selectByChangedSince(long time) {
            return new ShortcutListAsserter(this,
                    ShortcutManagerTestUtils.changedSince(mList, time));
        }

        public ShortcutListAsserter selectByIds(String... ids) {
            final Set<String> idSet = set(ids);
            final ArrayList<ShortcutInfo> selected = new ArrayList<>();
            for (ShortcutInfo si : mList) {
                if (idSet.contains(si.getId())) {
                    selected.add(si);
                    idSet.remove(si.getId());
                }
            }
            if (idSet.size() > 0) {
                fail("Shortcuts not found for IDs=" + idSet);
            }

            return new ShortcutListAsserter(this, selected);
        }

        public ShortcutListAsserter toSortByRank() {
            return new ShortcutListAsserter(this,
                    ShortcutManagerTestUtils.sortedByRank(mList));
        }

        public ShortcutListAsserter call(Consumer<List<ShortcutInfo>> c) {
            c.accept(mList);
            return this;
        }

        public ShortcutListAsserter haveIds(String... expectedIds) {
            assertShortcutIds(mList, expectedIds);
            return this;
        }

        public ShortcutListAsserter haveIdsOrdered(String... expectedIds) {
            assertShortcutIdsOrdered(mList, expectedIds);
            return this;
        }

        private ShortcutListAsserter haveSequentialRanks() {
            for (int i = 0; i < mList.size(); i++) {
                final ShortcutInfo si = mList.get(i);
                assertEquals("Rank not sequential: id=" + si.getId(), i, si.getRank());
            }
            return this;
        }

        public ShortcutListAsserter haveRanksInOrder(String... expectedIds) {
            toSortByRank()
                    .haveSequentialRanks()
                    .haveIdsOrdered(expectedIds);
            return this;
        }

        public ShortcutListAsserter isEmpty() {
            assertEquals(0, mList.size());
            return this;
        }

        public ShortcutListAsserter areAllDynamic() {
            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isDynamic()));
            return this;
        }

        public ShortcutListAsserter areAllNotDynamic() {
            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isDynamic()));
            return this;
        }

        public ShortcutListAsserter areAllPinned() {
            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isPinned()));
            return this;
        }

        public ShortcutListAsserter areAllNotPinned() {
            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isPinned()));
            return this;
        }

        public ShortcutListAsserter areAllManifest() {
            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isDeclaredInManifest()));
            return this;
        }

        public ShortcutListAsserter areAllNotManifest() {
            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isDeclaredInManifest()));
            return this;
        }

        public ShortcutListAsserter areAllImmutable() {
            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isImmutable()));
            return this;
        }

        public ShortcutListAsserter areAllMutable() {
            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isImmutable()));
            return this;
        }

        public ShortcutListAsserter areAllEnabled() {
            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isEnabled()));
            return this;
        }

        public ShortcutListAsserter areAllDisabled() {
            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isEnabled()));
            return this;
        }

        public ShortcutListAsserter areAllWithKeyFieldsOnly() {
            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.hasKeyFieldsOnly()));
            return this;
        }

        public ShortcutListAsserter areAllNotWithKeyFieldsOnly() {
            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.hasKeyFieldsOnly()));
            return this;
        }

        public ShortcutListAsserter areAllWithActivity(ComponentName activity) {
            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.getActivity().equals(activity)));
            return this;
        }

        public ShortcutListAsserter forAllShortcuts(Consumer<ShortcutInfo> sa) {
            boolean found = false;
            for (int i = 0; i < mList.size(); i++) {
                final ShortcutInfo si = mList.get(i);
                found = true;
                sa.accept(si);
            }
            assertTrue("No shortcuts found.", found);
            return this;
        }

        public ShortcutListAsserter forShortcut(Predicate<ShortcutInfo> p,
                Consumer<ShortcutInfo> sa) {
            boolean found = false;
            for (int i = 0; i < mList.size(); i++) {
                final ShortcutInfo si = mList.get(i);
                if (p.test(si)) {
                    found = true;
                    try {
                        sa.accept(si);
                    } catch (Throwable e) {
                        throw new AssertionError("Assertion failed for shortcut " + si.getId(), e);
                    }
                }
            }
            assertTrue("Shortcut with the given condition not found.", found);
            return this;
        }

        public ShortcutListAsserter forShortcutWithId(String id, Consumer<ShortcutInfo> sa) {
            forShortcut(si -> si.getId().equals(id), sa);

            return this;
        }
    }

    public static void assertBundlesEqual(BaseBundle b1, BaseBundle b2) {
        if (b1 == null && b2 == null) {
            return; // pass
        }
        assertNotNull(b1);
        assertNotNull(b2);

        // HashSet makes the error message readable.
        assertEquals(set(b1.keySet()), set(b2.keySet()));

        for (String key : b1.keySet()) {
            final Object v1 = b1.get(key);
            final Object v2 = b2.get(key);
            if (v1 == null) {
                if (v2 == null) {
                    return;
                }
            }
            if (v1.equals(v2)) {
                return;
            }

            assertTrue("Only either value is null: key=" + key
                    + " b1=" + b1 + " b2=" + b2, v1 != null && v2 != null);
            assertEquals("Class mismatch: key=" + key, v1.getClass(), v2.getClass());

            if (v1 instanceof BaseBundle) {
                assertBundlesEqual((BaseBundle) v1, (BaseBundle) v2);

            } else if (v1 instanceof boolean[]) {
                assertTrue(Arrays.equals((boolean[]) v1, (boolean[]) v2));

            } else if (v1 instanceof int[]) {
                MoreAsserts.assertEquals((int[]) v1, (int[]) v2);

            } else if (v1 instanceof double[]) {
                MoreAsserts.assertEquals((double[]) v1, (double[]) v2);

            } else if (v1 instanceof String[]) {
                MoreAsserts.assertEquals((String[]) v1, (String[]) v2);

            } else if (v1 instanceof Double) {
                if (((Double) v1).isNaN()) {
                    assertTrue(((Double) v2).isNaN());
                } else {
                    assertEquals(v1, v2);
                }

            } else {
                assertEquals(v1, v2);
            }
        }
    }

    public static void waitOnMainThread() throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(1);

        new Handler(Looper.getMainLooper()).post(() -> latch.countDown());

        latch.await();
    }

    public static class LauncherCallbackAsserter {
        private final LauncherApps.Callback mCallback = mock(LauncherApps.Callback.class);

        private Callback getMockCallback() {
            return mCallback;
        }

        public LauncherCallbackAsserter assertNoCallbackCalled() {
            verify(mCallback, times(0)).onShortcutsChanged(
                    anyString(),
                    any(List.class),
                    any(UserHandle.class));
            return this;
        }

        public LauncherCallbackAsserter assertNoCallbackCalledForPackage(
                String publisherPackageName) {
            verify(mCallback, times(0)).onShortcutsChanged(
                    eq(publisherPackageName),
                    any(List.class),
                    any(UserHandle.class));
            return this;
        }

        public LauncherCallbackAsserter assertNoCallbackCalledForPackageAndUser(
                String publisherPackageName, UserHandle publisherUserHandle) {
            verify(mCallback, times(0)).onShortcutsChanged(
                    eq(publisherPackageName),
                    any(List.class),
                    eq(publisherUserHandle));
            return this;
        }

        public ShortcutListAsserter assertCallbackCalledForPackageAndUser(
                String publisherPackageName, UserHandle publisherUserHandle) {
            final ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
            verify(mCallback, times(1)).onShortcutsChanged(
                    eq(publisherPackageName),
                    shortcuts.capture(),
                    eq(publisherUserHandle));
            return new ShortcutListAsserter(shortcuts.getValue());
        }
    }

    public static LauncherCallbackAsserter assertForLauncherCallback(
            LauncherApps launcherApps, Runnable body) throws InterruptedException {
        final LauncherCallbackAsserter asserter = new LauncherCallbackAsserter();
        launcherApps.registerCallback(asserter.getMockCallback(),
                new Handler(Looper.getMainLooper()));

        body.run();

        waitOnMainThread();

        launcherApps.unregisterCallback(asserter.getMockCallback());

        return asserter;
    }
}
