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

Commit f6d9f9d8 authored by JW Wang's avatar JW Wang
Browse files

Add tests for device config changes

Test device config changes are propagated correctly to the watchdog.

* Keep polling until the config value becomes the expected one.
* Remove listeners at the end of each test - too many device config
  listeners will delay the notification significantly ( > 1 min)
  according to my local experiments.

Bug: 181820350
Test: atest PackageWatchdogTest
Change-Id: Ia5e89b69a8052f49e6400f6b22313249d523786c
parent d38c0368
Loading
Loading
Loading
Loading
+25 −10
Original line number Diff line number Diff line
@@ -182,6 +182,9 @@ public class PackageWatchdog {
    private final Runnable mSaveToFile = this::saveToFile;
    private final SystemClock mSystemClock;
    private final BootThreshold mBootThreshold;
    private final DeviceConfig.OnPropertiesChangedListener
            mOnPropertyChangedListener = this::onPropertyChanged;

    // The set of packages that have been synced with the ExplicitHealthCheckController
    @GuardedBy("mLock")
    private Set<String> mRequestedHealthCheckPackages = new ArraySet<>();
@@ -669,12 +672,20 @@ public class PackageWatchdog {
        }
    }

    @VisibleForTesting
    long getTriggerFailureCount() {
        synchronized (mLock) {
            return mTriggerFailureCount;
        }
    }

    @VisibleForTesting
    long getTriggerFailureDurationMs() {
        synchronized (mLock) {
            return mTriggerFailureDurationMs;
        }
    }

    /**
     * Serializes and syncs health check requests with the {@link ExplicitHealthCheckController}.
     */
@@ -983,21 +994,25 @@ public class PackageWatchdog {
        }
    }

    private void onPropertyChanged(DeviceConfig.Properties properties) {
        try {
            updateConfigs();
        } catch (Exception ignore) {
            Slog.w(TAG, "Failed to reload device config changes");
        }
    }

    /** Adds a {@link DeviceConfig#OnPropertiesChangedListener}. */
    private void setPropertyChangedListenerLocked() {
        DeviceConfig.addOnPropertiesChangedListener(
                DeviceConfig.NAMESPACE_ROLLBACK,
                mContext.getMainExecutor(),
                (properties) -> {
                    if (!DeviceConfig.NAMESPACE_ROLLBACK.equals(properties.getNamespace())) {
                        return;
                mOnPropertyChangedListener);
    }
                    try {
                        updateConfigs();
                    } catch (Exception ignore) {
                        Slog.w(TAG, "Failed to reload device config changes");
                    }
                });

    @VisibleForTesting
    void removePropertyChangedListener() {
        DeviceConfig.removeOnPropertiesChangedListener(mOnPropertyChangedListener);
    }

    /**
+78 −1
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
@@ -79,11 +78,15 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Test PackageWatchdog.
 */
public class PackageWatchdogTest {
    private static final long RETRY_MAX_COUNT = 30;
    private static final long RETRY_TIMEOUT_MILLIS = 500;

    private static final String APP_A = "com.package.a";
    private static final String APP_B = "com.package.b";
    private static final String APP_C = "com.package.c";
@@ -109,6 +112,16 @@ public class PackageWatchdogTest {
    private MockitoSession mSession;
    private HashMap<String, String> mSystemSettingsMap;

    private boolean retry(Supplier<Boolean> supplier) throws Exception {
        for (int i = 0; i < RETRY_MAX_COUNT; ++i) {
            if (supplier.get()) {
                return true;
            }
            Thread.sleep(RETRY_TIMEOUT_MILLIS);
        }
        return false;
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
@@ -176,6 +189,10 @@ public class PackageWatchdogTest {
    public void tearDown() throws Exception {
        dropShellPermissions();
        mSession.finishMocking();
        // Clean up listeners since too many listeners will delay notifications significantly
        for (PackageWatchdog watchdog : mAllocatedWatchdogs) {
            watchdog.removePropertyChangedListener();
        }
        mAllocatedWatchdogs.clear();
    }

@@ -1282,6 +1299,66 @@ public class PackageWatchdogTest {
        assertTrue(readPkg.isEqualTo(expectedPkg));
    }

    /**
     * Tests device config changes are propagated correctly.
     */
    @Test
    public void testDeviceConfigChange_explicitHealthCheckEnabled() throws Exception {
        TestController controller = new TestController();
        PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */);
        assertThat(controller.mIsEnabled).isTrue();

        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                PackageWatchdog.PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED,
                Boolean.toString(false), /*makeDefault*/false);
        retry(() -> !controller.mIsEnabled);
        assertThat(controller.mIsEnabled).isFalse();
    }

    /**
     * Tests device config changes are propagated correctly.
     */
    @Test
    public void testDeviceConfigChange_triggerFailureCount() throws Exception {
        PackageWatchdog watchdog = createWatchdog();

        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
                Integer.toString(777), false);
        retry(() -> watchdog.getTriggerFailureCount() == 777);
        assertThat(watchdog.getTriggerFailureCount()).isEqualTo(777);

        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
                Integer.toString(0), false);
        retry(() -> watchdog.getTriggerFailureCount()
                == PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT);
        assertThat(watchdog.getTriggerFailureCount()).isEqualTo(
                PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT);
    }

    /**
     * Tests device config changes are propagated correctly.
     */
    @Test
    public void testDeviceConfigChange_triggerFailureDurationMs() throws Exception {
        PackageWatchdog watchdog = createWatchdog();

        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS,
                Integer.toString(888), false);
        retry(() -> watchdog.getTriggerFailureDurationMs() == 888);
        assertThat(watchdog.getTriggerFailureDurationMs()).isEqualTo(888);

        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS,
                Integer.toString(0), false);
        retry(() -> watchdog.getTriggerFailureDurationMs()
                == PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS);
        assertThat(watchdog.getTriggerFailureDurationMs()).isEqualTo(
                PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS);
    }

    private void adoptShellPermissions(String... permissions) {
        InstrumentationRegistry
                .getInstrumentation()