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

Commit f3f21501 authored by Julia Tuttle's avatar Julia Tuttle
Browse files

Convert ShadeListBuilderTest to use assertLogsWtfs

Bug: 309625167
Test: atest ShadeListBuilderTest
Flag: NA
Change-Id: I4b72dd5bcb0b73f9c44ec624adfdfe29fad71636
parent 07c778a1
Loading
Loading
Loading
Loading
+81 −112
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArrayMap;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -56,6 +55,7 @@ import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.log.LogAssertKt;
import com.android.systemui.statusbar.NotificationInteractionTracker;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
@@ -76,6 +76,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.util.time.FakeSystemClock;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -129,10 +130,6 @@ public class ShadeListBuilderTest extends SysuiTestCase {
    private Map<String, Integer> mNextIdMap = new ArrayMap<>();
    private int mNextRank = 0;

    private Log.TerribleFailureHandler mOldWtfHandler = null;
    private Log.TerribleFailure mLastWtf = null;
    private int mWtfCount = 0;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
@@ -1756,20 +1753,19 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.addPreGroupFilter(filter);
        mListBuilder.addOnBeforeTransformGroupsListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the filter is invalidated exactly
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
        addNotif(0, PACKAGE_2);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        dispatchBuild();
        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);

        // THEN an exception is NOT thrown directly, but a WTF IS logged.
        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        LogAssertKt.assertLogsWtfs(() -> {
            dispatchBuild();
            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
        });
    }

    @Test(expected = IllegalStateException.class)
    @Test
    public void testOutOfOrderPreGroupFilterInvalidationThrowsAfterTooManyRuns() {
        // GIVEN a PreGroupNotifFilter that gets invalidated during the grouping stage,
        NotifFilter filter = new PackageFilter(PACKAGE_1);
@@ -1778,20 +1774,20 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.addPreGroupFilter(filter);
        mListBuilder.addOnBeforeTransformGroupsListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the filter is invalidated more than
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,

        // THEN an exception IS thrown.

        addNotif(0, PACKAGE_2);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);

        LogAssertKt.assertLogsWtfs(() -> {
            Assert.assertThrows(IllegalStateException.class, () -> {
                dispatchBuild();
        try {
                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
        } finally {
            expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        }

        // THEN an exception IS thrown.
            });
        });
    }

    @Test
@@ -1803,26 +1799,30 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.addPreGroupFilter(filter);
        mListBuilder.addOnBeforeTransformGroupsListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the filter is invalidated
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, the pipeline runs for a non-reentrant reason,
        // and then the filter is invalidated MAX_CONSECUTIVE_REENTRANT_REBUILDS times again,

        // THEN an exception is NOT thrown, but WTFs ARE logged.

        addNotif(0, PACKAGE_2);

        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        LogAssertKt.assertLogsWtfs(() -> {
            dispatchBuild();
            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
        });

        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        LogAssertKt.assertLogsWtfs(() -> {
            // Note: dispatchBuild itself triggers a non-reentrant pipeline run.
            dispatchBuild();
            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);

        // THEN an exception is NOT thrown, but WTFs ARE logged.
        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS * 2);
        });
    }

    @Test
    public void testOutOfOrderPrompterInvalidationDoesNotThrowBeforeTooManyRuns() {
    public void testOutOfOrderPromoterInvalidationDoesNotThrowBeforeTooManyRuns() {
        // GIVEN a NotifPromoter that gets invalidated during the sorting stage,
        NotifPromoter promoter = new IdPromoter(47);
        CountingInvalidator invalidator = new CountingInvalidator(promoter);
@@ -1830,22 +1830,22 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.addPromoter(promoter);
        mListBuilder.addOnBeforeSortListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the promoter is invalidated exactly
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,

        // THEN an exception is NOT thrown directly, but a WTF IS logged.

        addNotif(0, PACKAGE_1);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);

        LogAssertKt.assertLogsWtfs(() -> {
            dispatchBuild();
            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);

        // THEN an exception is NOT thrown directly, but a WTF IS logged.
        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);

        });
    }

    @Test(expected = IllegalStateException.class)
    public void testOutOfOrderPrompterInvalidationThrowsAfterTooManyRuns() {
    @Test
    public void testOutOfOrderPromoterInvalidationThrowsAfterTooManyRuns() {
        // GIVEN a NotifPromoter that gets invalidated during the sorting stage,
        NotifPromoter promoter = new IdPromoter(47);
        CountingInvalidator invalidator = new CountingInvalidator(promoter);
@@ -1853,20 +1853,20 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.addPromoter(promoter);
        mListBuilder.addOnBeforeSortListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the promoter is invalidated more than
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,

        // THEN an exception IS thrown.

        addNotif(0, PACKAGE_1);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);

        LogAssertKt.assertLogsWtfs(() -> {
            Assert.assertThrows(IllegalStateException.class, () -> {
                dispatchBuild();
        try {
                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
        } finally {
            expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        }

        // THEN an exception IS thrown.
            });
        });
    }

    @Test
@@ -1878,20 +1878,21 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.setComparators(singletonList(comparator));
        mListBuilder.addOnBeforeRenderListListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the comparator is invalidated exactly
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,

        // THEN an exception is NOT thrown directly, but a WTF IS logged.

        addNotif(0, PACKAGE_2);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);

        LogAssertKt.assertLogsWtfs(() -> {
            dispatchBuild();
            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);

        // THEN an exception is NOT thrown directly, but a WTF IS logged.
        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        });
    }

    @Test(expected = IllegalStateException.class)
    @Test
    public void testOutOfOrderComparatorInvalidationThrowsAfterTooManyRuns() {
        // GIVEN a NotifComparator that gets invalidated during the finalizing stage,
        NotifComparator comparator = new HypeComparator(PACKAGE_1);
@@ -1900,16 +1901,20 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.setComparators(singletonList(comparator));
        mListBuilder.addOnBeforeRenderListListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the comparator is invalidated more than
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,

        // THEN an exception IS thrown.

        addNotif(0, PACKAGE_2);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);

        LogAssertKt.assertLogsWtfs(() -> {
            Assert.assertThrows(IllegalStateException.class, () -> {
                dispatchBuild();
                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);

        // THEN an exception IS thrown.
            });
        });
    }

    @Test
@@ -1921,20 +1926,21 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.addFinalizeFilter(filter);
        mListBuilder.addOnBeforeRenderListListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the PreRenderFilter is invalidated exactly
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,

        // THEN an exception is NOT thrown directly, but a WTF IS logged.

        addNotif(0, PACKAGE_2);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);

        LogAssertKt.assertLogsWtfs(() -> {
            dispatchBuild();
            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);

        // THEN an exception is NOT thrown directly, but a WTF IS logged.
        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        });
    }

    @Test(expected = IllegalStateException.class)
    @Test
    public void testOutOfOrderPreRenderFilterInvalidationThrowsAfterTooManyRuns() {
        // GIVEN a PreRenderNotifFilter that gets invalidated during the finalizing stage,
        NotifFilter filter = new PackageFilter(PACKAGE_1);
@@ -1943,57 +1949,20 @@ public class ShadeListBuilderTest extends SysuiTestCase {
        mListBuilder.addFinalizeFilter(filter);
        mListBuilder.addOnBeforeRenderListListener(listener);

        interceptWtfs();

        // WHEN we try to run the pipeline and the PreRenderFilter is invalidated more than
        // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
        addNotif(0, PACKAGE_2);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
        dispatchBuild();
        try {
            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
        } finally {
            expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
        }

        // THEN an exception IS thrown.
    }

    private void interceptWtfs() {
        assertNull(mOldWtfHandler);

        mLastWtf = null;
        mWtfCount = 0;
        addNotif(0, PACKAGE_2);
        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);

        mOldWtfHandler = Log.setWtfHandler((tag, e, system) -> {
            Log.e("ShadeListBuilderTest", "Observed WTF: " + e);
            mLastWtf = e;
            mWtfCount++;
        LogAssertKt.assertLogsWtfs(() -> {
            Assert.assertThrows(IllegalStateException.class, () -> {
                dispatchBuild();
                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
            });
        });
    }

    private void expectNoWtfs() {
        assertNull(expectWtfs(0));
    }

    private Log.TerribleFailure expectWtf() {
        return expectWtfs(1);
    }

    private Log.TerribleFailure expectWtfs(int expectedWtfCount) {
        assertNotNull(mOldWtfHandler);

        Log.setWtfHandler(mOldWtfHandler);
        mOldWtfHandler = null;

        Log.TerribleFailure wtf = mLastWtf;
        int wtfCount = mWtfCount;

        mLastWtf = null;
        mWtfCount = 0;

        assertEquals(expectedWtfCount, wtfCount);
        return wtf;
    }

    @Test
+11 −0
Original line number Diff line number Diff line
@@ -59,6 +59,17 @@ fun assertLogsWtf(
): TerribleFailureLog =
    assertLogsWtf(message = message, allowMultiple = allowMultiple) { loggingRunnable.run() }

fun assertLogsWtfs(
    message: String = "Expected Log.wtf to be called once or more",
    loggingBlock: () -> Unit,
): TerribleFailureLog = assertLogsWtf(message, allowMultiple = true, loggingBlock)

@JvmOverloads
fun assertLogsWtfs(
    message: String = "Expected Log.wtf to be called once or more",
    loggingRunnable: Runnable,
): TerribleFailureLog = assertLogsWtfs(message) { loggingRunnable.run() }

/** The data passed to [TerribleFailureHandler.onTerribleFailure] */
data class TerribleFailureLog(
    val tag: String,