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

Commit 82228f22 authored by JW Wang's avatar JW Wang
Browse files

Move testNetworkFailedRollback (2/n)

Bug: 147785893
Test: atest NetworkStagedRollbackTest
Change-Id: I801499b760e38a1eec4bab69daaa533124ad9531
parent 45b0fc87
Loading
Loading
Loading
Loading
+129 −0
Original line number Diff line number Diff line
@@ -16,22 +16,98 @@

package com.android.tests.rollback.host;

import static org.junit.Assert.assertTrue;
import static org.testng.Assert.assertThrows;

import com.android.tradefed.device.LogcatReceiver;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Runs the network rollback tests.
 */
@RunWith(DeviceJUnit4ClassRunner.class)
public class NetworkStagedRollbackTest extends BaseHostJUnit4Test {
    /**
     * Runs the given phase of a test by calling into the device.
     * Throws an exception if the test phase fails.
     * <p>
     * For example, <code>runPhase("testApkOnlyEnableRollback");</code>
     */
    private void runPhase(String phase) throws Exception {
        assertTrue(runDeviceTests("com.android.tests.rollback",
                "com.android.tests.rollback.NetworkStagedRollbackTest",
                phase));
    }

    private static final String REASON_EXPLICIT_HEALTH_CHECK = "REASON_EXPLICIT_HEALTH_CHECK";

    private static final String ROLLBACK_INITIATE = "ROLLBACK_INITIATE";
    private static final String ROLLBACK_BOOT_TRIGGERED = "ROLLBACK_BOOT_TRIGGERED";

    private LogcatReceiver mReceiver;

    @Before
    public void setUp() throws Exception {
        mReceiver =  new LogcatReceiver(getDevice(), "logcat -s WatchdogRollbackLogger",
                getDevice().getOptions().getMaxLogcatDataSize(), 0);
        mReceiver.start();
    }

    @After
    public void tearDown() throws Exception {
        mReceiver.stop();
        mReceiver.clear();
    }

    /**
     * Tests failed network health check triggers watchdog staged rollbacks.
     */
    @Test
    public void testNetworkFailedRollback() throws Exception {
        try {
            // Disconnect internet so we can test network health triggered rollbacks
            getDevice().executeShellCommand("svc wifi disable");
            getDevice().executeShellCommand("svc data disable");

            runPhase("testNetworkFailedRollback_Phase1");
            // Reboot device to activate staged package
            getDevice().reboot();

            // Verify rollback was enabled
            runPhase("testNetworkFailedRollback_Phase2");
            assertThrows(AssertionError.class, () -> runPhase("testNetworkFailedRollback_Phase3"));

            getDevice().waitForDeviceAvailable();
            // Verify rollback was executed after health check deadline
            runPhase("testNetworkFailedRollback_Phase4");
            InputStreamSource logcatStream = mReceiver.getLogcatData();
            try {
                List<String> watchdogEvents = getWatchdogLoggingEvents(logcatStream);
                assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_INITIATE, null,
                        REASON_EXPLICIT_HEALTH_CHECK, null));
                assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
                        null, null));
            } finally {
                logcatStream.close();
            }
        } finally {
            // Reconnect internet again so we won't break tests which assume internet available
            getDevice().executeShellCommand("svc wifi enable");
            getDevice().executeShellCommand("svc data enable");
        }
    }

    /**
@@ -40,4 +116,57 @@ public class NetworkStagedRollbackTest extends BaseHostJUnit4Test {
    @Test
    public void testNetworkPassedDoesNotRollback() throws Exception {
    }

    /**
     * Returns a list of all Watchdog logging events which have occurred.
     */
    private List<String> getWatchdogLoggingEvents(InputStreamSource inputStreamSource)
            throws Exception {
        List<String> watchdogEvents = new ArrayList<>();
        InputStream inputStream = inputStreamSource.createInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.contains("Watchdog event occurred")) {
                watchdogEvents.add(line);
            }
        }
        return watchdogEvents;
    }

    /**
     * Returns whether a Watchdog event has occurred that matches the given criteria.
     *
     * Check the value of all non-null parameters against the list of Watchdog events that have
     * occurred, and return {@code true} if an event exists which matches all criteria.
     */
    private boolean watchdogEventOccurred(List<String> loggingEvents,
            String type, String logPackage,
            String rollbackReason, String failedPackageName) throws Exception {
        List<String> eventCriteria = new ArrayList<>();
        if (type != null) {
            eventCriteria.add("type: " + type);
        }
        if (logPackage != null) {
            eventCriteria.add("logPackage: " + logPackage);
        }
        if (rollbackReason != null) {
            eventCriteria.add("rollbackReason: " + rollbackReason);
        }
        if (failedPackageName != null) {
            eventCriteria.add("failedPackageName: " + failedPackageName);
        }
        for (String loggingEvent: loggingEvents) {
            boolean matchesCriteria = true;
            for (String criterion: eventCriteria) {
                if (!loggingEvent.contains(criterion)) {
                    matchesCriteria = false;
                }
            }
            if (matchesCriteria) {
                return true;
            }
        }
        return false;
    }
}
+134 −0
Original line number Diff line number Diff line
@@ -16,9 +16,143 @@

package com.android.tests.rollback;

import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat;
import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage;

import android.Manifest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.rollback.RollbackManager;
import android.os.ParcelFileDescriptor;
import android.provider.DeviceConfig;

import androidx.test.platform.app.InstrumentationRegistry;

import com.android.cts.install.lib.Install;
import com.android.cts.install.lib.InstallUtils;
import com.android.cts.install.lib.TestApp;
import com.android.cts.rollback.lib.RollbackUtils;

import libcore.io.IoUtils;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.io.File;
import java.util.concurrent.TimeUnit;

@RunWith(JUnit4.class)
public class NetworkStagedRollbackTest {
    private static final String NETWORK_STACK_CONNECTOR_CLASS =
            "android.net.INetworkStackConnector";
    private static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS =
            "watchdog_request_timeout_millis";

    private static final TestApp NETWORK_STACK = new TestApp("NetworkStack",
            getNetworkStackPackageName(), -1, false, findNetworkStackApk());

    private static File findNetworkStackApk() {
        final File apk = new File("/system/priv-app/NetworkStack/NetworkStack.apk");
        if (apk.isFile()) {
            return apk;
        }
        return new File("/system/priv-app/NetworkStackNext/NetworkStackNext.apk");
    }

    /**
     * Adopts common shell permissions needed for rollback tests.
     */
    @Before
    public void adoptShellPermissions() {
        InstallUtils.adoptShellPermissionIdentity(
                Manifest.permission.INSTALL_PACKAGES,
                Manifest.permission.DELETE_PACKAGES,
                Manifest.permission.TEST_MANAGE_ROLLBACKS,
                Manifest.permission.FORCE_STOP_PACKAGES,
                Manifest.permission.WRITE_DEVICE_CONFIG);
    }

    /**
     * Drops shell permissions needed for rollback tests.
     */
    @After
    public void dropShellPermissions() {
        InstallUtils.dropShellPermissionIdentity();
    }

    @Test
    public void testNetworkFailedRollback_Phase1() throws Exception {
        // Remove available rollbacks and uninstall NetworkStack on /data/
        RollbackManager rm = RollbackUtils.getRollbackManager();
        String networkStack = getNetworkStackPackageName();

        rm.expireRollbackForPackage(networkStack);
        uninstallNetworkStackPackage();

        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                networkStack)).isNull();

        // Reduce health check deadline
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS,
                Integer.toString(120000), false);
        // Simulate re-installation of new NetworkStack with rollbacks enabled
        installNetworkStackPackage();
    }

    @Test
    public void testNetworkFailedRollback_Phase2() throws Exception {
        RollbackManager rm = RollbackUtils.getRollbackManager();
        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                getNetworkStackPackageName())).isNotNull();

        // Sleep for < health check deadline
        Thread.sleep(TimeUnit.SECONDS.toMillis(5));
        // Verify rollback was not executed before health check deadline
        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                getNetworkStackPackageName())).isNull();
    }

    @Test
    public void testNetworkFailedRollback_Phase3() throws Exception {
        // Sleep for > health check deadline (120s to trigger rollback + 120s to reboot)
        // The device is expected to reboot during sleeping. This device method will fail and
        // the host will catch the assertion. If reboot doesn't happen, the host will fail the
        // assertion.
        Thread.sleep(TimeUnit.SECONDS.toMillis(240));
    }

    @Test
    public void testNetworkFailedRollback_Phase4() throws Exception {
        RollbackManager rm = RollbackUtils.getRollbackManager();
        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                getNetworkStackPackageName())).isNotNull();
    }

    private static String getNetworkStackPackageName() {
        Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
        ComponentName comp = intent.resolveSystemService(
                InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(), 0);
        return comp.getPackageName();
    }

    private static void installNetworkStackPackage() throws Exception {
        Install.single(NETWORK_STACK).setStaged().setEnableRollback()
                .addInstallFlags(PackageManager.INSTALL_REPLACE_EXISTING).commit();
    }

    private static void uninstallNetworkStackPackage() {
        // Uninstall the package as a privileged user so we won't fail due to permission.
        runShellCommand("pm uninstall " + getNetworkStackPackageName());
    }

    private static void runShellCommand(String cmd) {
        ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .executeShellCommand(cmd);
        IoUtils.closeQuietly(pfd);
    }
}
+0 −49
Original line number Diff line number Diff line
@@ -274,55 +274,6 @@ public class StagedRollbackTest {
                TestApp.B)).isNotNull();
    }

    @Test
    public void testNetworkFailedRollback_Phase1() throws Exception {
        // Remove available rollbacks and uninstall NetworkStack on /data/
        RollbackManager rm = RollbackUtils.getRollbackManager();
        String networkStack = getNetworkStackPackageName();

        rm.expireRollbackForPackage(networkStack);
        uninstallNetworkStackPackage();

        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                        networkStack)).isNull();

        // Reduce health check deadline
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS,
                Integer.toString(120000), false);
        // Simulate re-installation of new NetworkStack with rollbacks enabled
        installNetworkStackPackage();
    }

    @Test
    public void testNetworkFailedRollback_Phase2() throws Exception {
        RollbackManager rm = RollbackUtils.getRollbackManager();
        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                        getNetworkStackPackageName())).isNotNull();

        // Sleep for < health check deadline
        Thread.sleep(TimeUnit.SECONDS.toMillis(5));
        // Verify rollback was not executed before health check deadline
        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                        getNetworkStackPackageName())).isNull();
    }

    @Test
    public void testNetworkFailedRollback_Phase3() throws Exception {
        // Sleep for > health check deadline (120s to trigger rollback + 120s to reboot)
        // The device is expected to reboot during sleeping. This device method will fail and
        // the host will catch the assertion. If reboot doesn't happen, the host will fail the
        // assertion.
        Thread.sleep(TimeUnit.SECONDS.toMillis(240));
    }

    @Test
    public void testNetworkFailedRollback_Phase4() throws Exception {
        RollbackManager rm = RollbackUtils.getRollbackManager();
        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                        getNetworkStackPackageName())).isNotNull();
    }

    private static String getNetworkStackPackageName() {
        Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
        ComponentName comp = intent.resolveSystemService(
+0 −38
Original line number Diff line number Diff line
@@ -227,44 +227,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
        }
    }

    /**
     * Tests failed network health check triggers watchdog staged rollbacks.
     */
    @Test
    public void testNetworkFailedRollback() throws Exception {
        try {
            // Disconnect internet so we can test network health triggered rollbacks
            getDevice().executeShellCommand("svc wifi disable");
            getDevice().executeShellCommand("svc data disable");

            runPhase("testNetworkFailedRollback_Phase1");
            // Reboot device to activate staged package
            getDevice().reboot();

            // Verify rollback was enabled
            runPhase("testNetworkFailedRollback_Phase2");
            assertThrows(AssertionError.class, () -> runPhase("testNetworkFailedRollback_Phase3"));

            getDevice().waitForDeviceAvailable();
            // Verify rollback was executed after health check deadline
            runPhase("testNetworkFailedRollback_Phase4");
            InputStreamSource logcatStream = mReceiver.getLogcatData();
            try {
                List<String> watchdogEvents = getWatchdogLoggingEvents(logcatStream);
                assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_INITIATE, null,
                                REASON_EXPLICIT_HEALTH_CHECK, null));
                assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
                        null, null));
            } finally {
                logcatStream.close();
            }
        } finally {
            // Reconnect internet again so we won't break tests which assume internet available
            getDevice().executeShellCommand("svc wifi enable");
            getDevice().executeShellCommand("svc data enable");
        }
    }

    /**
     * Tests passed network health check does not trigger watchdog staged rollbacks.
     */
+3 −0
Original line number Diff line number Diff line
@@ -6,6 +6,9 @@
    {
      "name": "StagedRollbackTest"
    },
    {
      "name": "NetworkStagedRollbackTest"
    },
    {
      "name": "MultiUserRollbackTest"
    }