/*
 * Copyright (C) 2021 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 android.accessibilityservice.cts;

import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.accessibility.cts.common.InstrumentedAccessibilityService;
import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.cts.activities.AccessibilityCacheActivity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.platform.test.annotations.AppModeFull;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;

import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;

import java.util.List;

@AppModeFull
@RunWith(AndroidJUnit4.class)
public class AccessibilityCacheTest {
    private static Instrumentation sInstrumentation;
    private static UiAutomation sUiAutomation;

    private InstrumentedAccessibilityService mService;
    private AccessibilityCacheActivity mActivity;

    private AccessibilityDumpOnFailureRule mDumpOnFailureRule =
            new AccessibilityDumpOnFailureRule();

    private final ActivityTestRule<AccessibilityCacheActivity> mActivityRule =
            new ActivityTestRule<>(AccessibilityCacheActivity.class, false, false);

    private InstrumentedAccessibilityServiceTestRule<InstrumentedAccessibilityService>
            mInstrumentedAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
            InstrumentedAccessibilityService.class, false);

    @Rule
    public final RuleChain mRuleChain = RuleChain
            .outerRule(mActivityRule)
            .around(mInstrumentedAccessibilityServiceRule)
            .around(mDumpOnFailureRule);

    @BeforeClass
    public static void oneTimeSetup() throws Exception {
        sInstrumentation = InstrumentationRegistry.getInstrumentation();
        sUiAutomation = sInstrumentation.getUiAutomation();
    }

    @AfterClass
    public static void postTestTearDown() {
        sUiAutomation.destroy();
    }

    @Before
    public void setUp() throws Exception {
        mService = mInstrumentedAccessibilityServiceRule.enableService();
        AccessibilityServiceInfo info = mService.getServiceInfo();
        info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
        mService.setServiceInfo(info);
        mActivity = launchActivityAndWaitForItToBeOnscreen(
                sInstrumentation, sUiAutomation, mActivityRule);
    }

    @Test
    public void enable_cacheEnabled() {
        assertTrue(mService.setCacheEnabled(false));
        assertFalse("Failed to disable", mService.isCacheEnabled());

        assertTrue(mService.setCacheEnabled(true));
        assertTrue("Failed to enable", mService.isCacheEnabled());
    }

    @Test
    public void disable_cacheDisabled() {
        assertTrue(mService.setCacheEnabled(false));
        assertFalse("Failed to disable", mService.isCacheEnabled());
    }

    @Test
    public void queryNode_nodeIsInCache() {
        AccessibilityNodeInfo info = mService.getRootInActiveWindow();
        assertTrue("Node is not in cache", mService.isNodeInCache(info));
    }

    @Test
    public void invalidateNode_nodeInCacheInvalidated() {
        AccessibilityNodeInfo info = mService.getRootInActiveWindow();
        assertTrue(mService.clearCachedSubtree(info));
        assertFalse("Node is still in cache", mService.isNodeInCache(info));
    }

    @Test
    public void invalidateNode_subtreeInCacheInvalidated() {
        // Tree is FrameLayout with TextView and LinearLayout children.
        // The LinearLayout has a TextView child.
        AccessibilityNodeInfo root = mService.getRootInActiveWindow();
        assertThat(root.getChildCount(), is(2));
        AccessibilityNodeInfo child0 = root.getChild(0);
        AccessibilityNodeInfo child1 = root.getChild(1);
        AccessibilityNodeInfo grandChild = child1.getChild(0);

        assertTrue(mService.clearCachedSubtree(root));

        assertFalse("Root is in cache", mService.isNodeInCache(root));
        assertFalse("Child0 is in cache", mService.isNodeInCache(child0));
        assertFalse("Child1 is in cache", mService.isNodeInCache(child1));
        assertFalse("Grandchild is in cache", mService.isNodeInCache(grandChild));
    }

    @Test
    public void clear_cacheInvalidated() {
        // Tree is FrameLayout with TextView and LinearLayout children.
        // The LinearLayout has a TextView child.
        AccessibilityNodeInfo root = mService.getRootInActiveWindow();
        assertThat(root.getChildCount(), is(2));
        AccessibilityNodeInfo child0 = root.getChild(0);
        AccessibilityNodeInfo child1 = root.getChild(1);
        AccessibilityNodeInfo grandChild = child1.getChild(0);

        assertTrue(mService.clearCache());

        assertFalse("Root is in cache", mService.isNodeInCache(root));
        assertFalse("Child0 is in cache", mService.isNodeInCache(child0));
        assertFalse("Child1 is in cache", mService.isNodeInCache(child1));
        assertFalse("Grandchild is in cache", mService.isNodeInCache(grandChild));
    }

    @Test
    public void getChild_descendantNotPrefetched() {
        // Tree is FrameLayout with TextView and LinearLayout children.
        // The LinearLayout has a TextView child.
        AccessibilityNodeInfo frameRoot = mService.getRootInActiveWindow();
        assertThat(frameRoot.getChildCount(), is(2));
        AccessibilityNodeInfo textViewChild = frameRoot.getChild(0);
        AccessibilityNodeInfo linearLayoutChild = frameRoot.getChild(1);
        AccessibilityNodeInfo frameGrandChild = linearLayoutChild.getChild(0);

        // Clear cache.
        assertTrue(mService.clearCachedSubtree(frameRoot));
        frameRoot.getChild(1, AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
                | AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE);
        assertTrue("Root is not in cache", mService.isNodeInCache(frameRoot));
        assertTrue("TextView is not in cache", mService.isNodeInCache(textViewChild));
        assertTrue("LinearLayout is not in cache", mService.isNodeInCache(linearLayoutChild));
        // No descendant prefetching
        assertFalse("Root grandchild is in cache", mService.isNodeInCache(frameGrandChild));
    }

    @Test
    public void getChild_descendantPrefetched() {
        // Tree is FrameLayout with TextView and LinearLayout children.
        // The LinearLayout has a TextView child.
        AccessibilityNodeInfo frameRoot = mService.getRootInActiveWindow();
        assertThat(frameRoot.getChildCount(), is(2));
        AccessibilityNodeInfo textViewChild = frameRoot.getChild(0);
        AccessibilityNodeInfo linearLayoutChild = frameRoot.getChild(1);
        AccessibilityNodeInfo frameGrandChild = linearLayoutChild.getChild(0);

        // Clear cache.
        assertTrue(mService.clearCachedSubtree(frameRoot));

        frameRoot.getChild(1, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST
                | AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE);

        assertFalse("Root is in cache", mService.isNodeInCache(frameRoot));
        assertFalse("TextView is in cache", mService.isNodeInCache(textViewChild));
        assertTrue("LinearLayout is not in cache", mService.isNodeInCache(linearLayoutChild));
        // Descendant prefetching
        assertTrue("Root grandchild is not in cache", mService.isNodeInCache(frameGrandChild));
    }

    @Test
    public void getParent_ancestorsPrefetched() {
        // Tree is FrameLayout with TextView and LinearLayout children.
        // The LinearLayout has a TextView child.
        AccessibilityNodeInfo frameRoot = mService.getRootInActiveWindow();
        assertThat(frameRoot.getChildCount(), is(2));
        AccessibilityNodeInfo textViewChild = frameRoot.getChild(0);
        AccessibilityNodeInfo linearLayoutChild = frameRoot.getChild(1);
        AccessibilityNodeInfo frameGrandChild = linearLayoutChild.getChild(0);

        // Clear cache.
        assertTrue(mService.clearCachedSubtree(frameRoot));

        frameGrandChild.getParent(AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS
                | AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE);

        assertTrue("Root is not in cache", mService.isNodeInCache(frameRoot));
        assertFalse("TextView is in cache", mService.isNodeInCache(textViewChild));
        assertTrue("linearLayout is not in cache", mService.isNodeInCache(linearLayoutChild));
        // Grandchild itself isn't in the cache
        assertFalse("root grandchild is in cache", mService.isNodeInCache(frameGrandChild));
    }

    /**
     * Tests a request that prefetches descendants with multiple strategies. This throws an
     * exception.
     */
    @Test
    public void testRequest_withMultiplePrefetchingStrategies_throwsException() {
        // Tree is FrameLayout with TextView and LinearLayout children.
        // The LinearLayout has a TextView child.
        AccessibilityNodeInfo root = mService.getRootInActiveWindow();
        assertThat(root.getChildCount(), is(2));

        // Clear cache.
        mService.clearCachedSubtree(root);

        assertThrows(IllegalArgumentException.class, () -> {
            root.getChild(0,
                    AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST
                            | AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_HYBRID);
        });
    }

    @Test
    public void testRequest_prefetchWithA11yWindowInfo() {
        List<AccessibilityWindowInfo> windows = mService.getWindows();
        AccessibilityWindowInfo activityWindowInfo = null;
        for (AccessibilityWindowInfo window : windows) {
            if (window.getTitle() != null
                    && TextUtils.equals(window.getTitle(), mActivity.getTitle())) {
                activityWindowInfo = window;
            }
        }

        assertNotNull(activityWindowInfo);
        AccessibilityNodeInfo windowRoot = activityWindowInfo.getRoot();

        assertThat(windowRoot.getChildCount(), is(2));
        AccessibilityNodeInfo textViewChild = windowRoot.getChild(0);
        AccessibilityNodeInfo linearLayoutChild = windowRoot.getChild(1);
        AccessibilityNodeInfo frameGrandChild = linearLayoutChild.getChild(0);

        // Clear cache.
        assertTrue(mService.clearCachedSubtree(windowRoot));

        AccessibilityNodeInfo windowRoot2 = activityWindowInfo.getRoot(
                AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
                        | AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE);
        // Confirm roots are the same.
        assertEquals(windowRoot, windowRoot2);
        assertFalse("Root is in cache", mService.isNodeInCache(windowRoot));
        assertFalse("TextView is in cache", mService.isNodeInCache(textViewChild));
        assertFalse("LinearLayout is in cache", mService.isNodeInCache(linearLayoutChild));
        assertFalse("Root grandchild is in cache", mService.isNodeInCache(frameGrandChild));
    }

    @Test
    public void testRequest_prefetchWithRootInActiveWindow() {
        // Tree is FrameLayout with TextView and LinearLayout children.
        // The LinearLayout has a TextView child.
        AccessibilityNodeInfo frameRoot = mService.getRootInActiveWindow();
        assertThat(frameRoot.getChildCount(), is(2));
        AccessibilityNodeInfo textViewChild = frameRoot.getChild(0);
        AccessibilityNodeInfo linearLayoutChild = frameRoot.getChild(1);
        AccessibilityNodeInfo frameGrandChild = linearLayoutChild.getChild(0);

        // Clear cache.
        assertTrue(mService.clearCachedSubtree(frameRoot));

        AccessibilityNodeInfo frameRoot2 = mService.getRootInActiveWindow(
                AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
                        | AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE);
        // Confirm roots are the same.
        assertEquals(frameRoot, frameRoot2);
        assertTrue("Root is in cache", mService.isNodeInCache(frameRoot2));
        assertFalse("TextView is in cache", mService.isNodeInCache(textViewChild));
        assertFalse("LinearLayout is in cache", mService.isNodeInCache(linearLayoutChild));
        assertFalse("Root grandchild is in cache", mService.isNodeInCache(frameGrandChild));
    }
}
