Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1d9e10d authored by Lee Shombert's avatar Lee Shombert
Browse files

Add a cache dumpsys test

This adds unit test to verify that dumpsys cacheinfo is working more
or less as intended.  The test is not exhaustive but should detect
uncaught exceptions during the dumpsys.

A documentation error in IpcDataCache is also fixed.

Flag: EXEMPT test-only
Bug: 406502093
Test: atest
 * FrameworksCoreTests:PropertyInvalidatedCacheTests
 * FrameworksCoreTests:IpcDataCacheTest
 * CtsOsTestCases:IpcDataCacheTest
Change-Id: I2add682e97528fba5a496cba5dc85cf258eb11d8
parent 10c3d590
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
@@ -2394,9 +2393,11 @@ public class PropertyInvalidatedCache<Query, Result> {
     * provided {@link PrintWriter}.  Optional switches allow the caller to choose
     * specific caches (selection is by cache name or property name); if these switches
     * are used then the output includes both cache statistics and cache entries.
     * @hide
     */
    @VisibleForTesting
    @NeverCompile
    private static void dumpCacheInfo(@NonNull PrintWriter pw, @NonNull String[] args) {
    public static void dumpCacheInfo(@NonNull PrintWriter pw, @NonNull String[] args) {
        if (!sEnabled) {
            pw.println("  Caching is disabled in this process.");
            return;
+1 −17
Original line number Diff line number Diff line
@@ -24,26 +24,10 @@ import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.PropertyInvalidatedCache;
import android.app.PropertyInvalidatedCache.Args;
import android.text.TextUtils;
import android.util.ArraySet;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FastPrintWriter;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * LRU cache that's invalidated when an opaque value in a property changes. Self-synchronizing,
@@ -411,7 +395,7 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query,
     * 1. Instance-per-cache: create a static instance of this class using the same
     *    parameters as would have been given to IpcDataCache (or
     *    PropertyInvalidatedCache).  This static instance provides a hook for the
     *    invalidateCache() and disableForLocalProcess() calls, which, generally, must
     *    invalidateCache() and disableForCurrentProcess() calls, which, generally, must
     *    also be static.
     *
     * 2. Short-hand for shared configuration parameters: create an instance of this class
+79 −5
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM;
import static android.app.PropertyInvalidatedCache.MODULE_TEST;
import static android.app.PropertyInvalidatedCache.NonceStore.INVALID_NONCE_INDEX;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -33,17 +35,13 @@ import static org.junit.Assert.fail;

import android.annotation.SuppressLint;
import android.app.PropertyInvalidatedCache.Args;
import android.app.PropertyInvalidatedCache.NonceWatcher;
import android.app.PropertyInvalidatedCache.NonceStore;
import android.app.PropertyInvalidatedCache.NonceWatcher;
import android.os.Binder;
import android.util.Log;
import com.android.internal.os.ApplicationSharedMemory;

import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.ravenwood.RavenwoodRule;

import androidx.test.filters.SmallTest;

@@ -54,6 +52,8 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
@@ -800,4 +800,78 @@ public class PropertyInvalidatedCacheTests {
        // The recompute is 4 because nulls were not cached.
        assertEquals(4, cache.getRecomputeCount());
    }

    // Collect the dumpsys output.  The boolean is for brief output.
    private static String getDumpsys(boolean brief) {
        final String[] args;
        if (brief) {
            args = new String[] { "-brief" };
        } else {
            args = new String[0];
        }

        ByteArrayOutputStream barray = new ByteArrayOutputStream();
        PrintWriter bout = new PrintWriter(barray);
        PropertyInvalidatedCache.dumpCacheInfo(bout, args);
        bout.close();
        return barray.toString();
    }

    @Test
    public void testDumpsysCacheinfo() {
        // Construct one well-known cache.
        TestCache cache = new TestCache(new Args(MODULE_TEST)
                .maxEntries(4).api("testDumpsys").cacheNulls(true),
                new TestQuery());
        cache.invalidateCache();

        String dump = getDumpsys(/* brief */ false);
        String p;

        // Test of the test.  If this test fails, it is likely that the dumpsys is badly broken.
        p = "Cache-key:";
        assertThat(dump).containsMatch(p);

        // Test of the test: this should fail.  This is not a functional test: if this test passes
        // then the logic in this test routine is faulty.
        p = "Cache-key: +notACache\\R +invalidated:1";
        assertThat(dump).doesNotContainMatch(p);

        // Verify that there is a handler for test/testDumpsys and it has one invalidation.
        p = "Cache-key: +test/testDumpsys\\R +invalidated:1";
        assertThat(dump).containsMatch(p);

        // Verify that the testDumpsys cache is present.  It has zero hits, misses, and clears.
        p = "Cache Name: testDumpsys\\R +Key: test/testDumpsys\\R"
            + " +Hits: 0, Misses: 0, Skips: 0";
        assertThat(dump).containsMatch(p);

        // Verify that the well-known cache getApplicationInfo is present.
        p = "Cache Name: getApplicationInfo";
        assertThat(dump).containsMatch(p);

        // Construct a brief listing.
        dump = getDumpsys(/* brief */ true);

        // Verify that there is a handler for test/testDumpsys and it has one invalidation.
        p = "Cache-key: +test/testDumpsys\\R +invalidated:1";
        assertThat(dump).containsMatch(p);

        // Verify that the testDumpsys cache is present.  It has zero hits, misses, and clears.
        p = "Cache Name: testDumpsys";
        assertThat(dump).doesNotContainMatch(p);

        // Add some activity.  Two misses and one hit.
        cache.query(1);
        cache.query(2);
        cache.query(1);

        // Construct a brief listing.
        dump = getDumpsys(/* brief */ true);

        // Verify that testDumpsys cache is present and it has the expected attributes.
        p = "Cache Name: testDumpsys\\R +Key: test/testDumpsys\\R"
            + " +Hits: 1, Misses: 2, Skips: 0";
        assertThat(dump).containsMatch(p);
    }
}