/*
 * Copyright (C) 2019 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.cts.backup;

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

import android.platform.test.annotations.AppModeFull;

import com.android.compatibility.common.util.BackupUtils;
import com.android.compatibility.common.util.ProtoUtils;
import com.android.server.job.JobSchedulerServiceDumpProto;
import com.android.server.job.JobStatusShortInfoProto;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;

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

import java.util.Optional;

/** Test that key-value and full backup jobs are scheduled in a profile. */
@RunWith(DeviceJUnit4ClassRunner.class)
@AppModeFull
public class ProfileScheduledJobHostSideTest extends BaseMultiUserBackupHostSideTest {
    private static final String PACKAGE_MANAGER_SENTINEL = "@pm@";

    /** From {@link com.android.server.backup.KeyValueBackupJob}. */
    private static final int KEY_VALUE_MIN_JOB_ID = 52417896;

    private static final String KEY_VALUE_JOB_NAME =
            "android/com.android.server.backup.KeyValueBackupJob";

    /** From {@link com.android.server.backup.FullBackupJob}. */
    private static final int FULL_BACKUP_MIN_JOB_ID = 52418896;

    private static final String FULL_BACKUP_JOB_NAME =
            "android/com.android.server.backup.FullBackupJob";

    private static final String TAG = "ProfileScheduledJobHostSideTest";
    private static final String LOGCAT_FILTER =
            "BackupManagerService:* KeyValueBackupTask:* PFTBT:* " + TAG + ":* *:S";
    private static final String KEY_VALUE_SUCCESS_LOG = "K/V backup pass finished";
    private static final String FULL_BACKUP_SUCCESS_LOG = "Full data backup pass finished";
    private static final int TIMEOUT_FOR_KEY_VALUE_SECONDS = 5 * 60; // 5 minutes.
    private static final int TIMEOUT_FOR_FULL_BACKUP_SECONDS = 5 * 60; // 5 minutes.

    private static final String JOB_SCHEDULER_RUN_COMMAND = "cmd jobscheduler run -f android";
    private static final String LOGCAT_BUFFER_SIZE_GET_COMMAND =
            "logcat -g | grep -E -o '[0-9]*([[:space:]]KiB|[[:space:]]MiB)' | head -1";
    private static final String LOGCAT_BUFFER_SIZE_SET_COMMAND = "logcat -G ";
    private static final String LOGCAT_MAX_BUFFER_SIZE = "16MiB";

    private final BackupUtils mBackupUtils = getBackupUtils();
    private ITestDevice mDevice;
    private Optional<Integer> mProfileUserId = Optional.empty();

    /** Create a profile user and switch to the local transport. */
    @Before
    @Override
    public void setUp() throws Exception {
        mDevice = getDevice();
        super.setUp();

        int parentUserId = mDevice.getCurrentUser();
        int profileUserId = createProfileUser(parentUserId, "Profile-Jobs");
        mProfileUserId = Optional.of(profileUserId);
        startUserAndInitializeForBackup(profileUserId);

        switchUserToLocalTransportAndAssertSuccess(profileUserId);
    }

    /** Remove the profile. */
    @After
    @Override
    public void tearDown() throws Exception {
        if (mProfileUserId.isPresent()) {
            mDevice.removeUser(mProfileUserId.get());
            mProfileUserId = Optional.empty();
        }
        super.tearDown();
    }

    /** Assert that the key value backup job for the profile is scheduled. */
    @Test
    public void testKeyValueBackupJobScheduled() throws Exception {
        int jobId = getJobIdForUser(KEY_VALUE_MIN_JOB_ID, mProfileUserId.get());
        assertThat(isSystemJobScheduled(jobId, KEY_VALUE_JOB_NAME)).isTrue();
    }

    /**
     * Tests the flow of the key value backup job for the profile.
     *
     * <ol>
     *   <li>Install key value backup app to ensure eligibility.
     *   <li>Force run the key value backup job.
     *   <li>Assert success via logcat.
     *   <li>Check that the job was rescheduled.
     * </ol>
     */
    @Test
    public void testKeyValueBackupJobRunsSuccessfully() throws Exception {
        int profileUserId = mProfileUserId.get();
        // Install a new key value backup app.
        installPackageAsUser(KEY_VALUE_APK, profileUserId);

        String previousBufferSize = mBackupUtils.executeShellCommandAndReturnOutput(
                LOGCAT_BUFFER_SIZE_GET_COMMAND);
        // Remove all whitespaces and non-visible characters
        previousBufferSize = previousBufferSize.replaceAll("\\s+", "");

        mBackupUtils.executeShellCommandSync(
                LOGCAT_BUFFER_SIZE_SET_COMMAND + LOGCAT_MAX_BUFFER_SIZE);

        // Force run k/v job.
        String startLog = mLogcatInspector.mark(TAG);
        int jobId = getJobIdForUser(KEY_VALUE_MIN_JOB_ID, profileUserId);
        mBackupUtils.executeShellCommandSync(JOB_SCHEDULER_RUN_COMMAND + " " + jobId);

        // Check logs for success.
        mLogcatInspector.assertLogcatContainsInOrder(
                LOGCAT_FILTER, TIMEOUT_FOR_KEY_VALUE_SECONDS, startLog, KEY_VALUE_SUCCESS_LOG);

        // Check job rescheduled.
        assertThat(isSystemJobScheduled(jobId, KEY_VALUE_JOB_NAME)).isTrue();

        mBackupUtils.executeShellCommandSync(LOGCAT_BUFFER_SIZE_SET_COMMAND + previousBufferSize);
    }

    /** Stop the profile user and assert that the key value job is no longer scheduled. */
    @Test
    public void testKeyValueBackupJobCancelled() throws Exception {
        int profileUserId = mProfileUserId.get();
        int jobId = getJobIdForUser(KEY_VALUE_MIN_JOB_ID, profileUserId);
        assertThat(isSystemJobScheduled(jobId, KEY_VALUE_JOB_NAME)).isTrue();

        mDevice.stopUser(profileUserId, /* waitFlag */ true, /* forceFlag */ true);

        assertThat(isSystemJobScheduled(jobId, KEY_VALUE_JOB_NAME)).isFalse();
    }

    /** Assert that the full backup job for the profile is scheduled. */
    @Test
    public void testFullBackupJobScheduled() throws Exception {
        int jobId = getJobIdForUser(FULL_BACKUP_MIN_JOB_ID, mProfileUserId.get());
        assertThat(isSystemJobScheduled(jobId, FULL_BACKUP_JOB_NAME)).isTrue();
    }

    /**
     * Tests the flow of the full backup job for the profile.
     *
     * <ol>
     *   <li>Install full backup app to ensure eligibility.
     *   <li>Force run the full backup job.
     *   <li>Assert success via logcat.
     *   <li>Check that the job was rescheduled.
     * </ol>
     */
    @Test
    public void testFullBackupJobRunsSuccessfully() throws Exception {
        int profileUserId = mProfileUserId.get();
        // Install a new eligible full backup app and run a backup pass for @pm@ as we cannot
        // perform a full backup pass before @pm@ is backed up.
        installPackageAsUser(FULL_BACKUP_APK, profileUserId);
        mBackupUtils.backupNowAndAssertSuccessForUser(PACKAGE_MANAGER_SENTINEL, profileUserId);

        String previousBufferSize = mBackupUtils.executeShellCommandAndReturnOutput(
                LOGCAT_BUFFER_SIZE_GET_COMMAND);
        // Remove all whitespaces and non-visible characters
        previousBufferSize = previousBufferSize.replaceAll("\\s+", "");

        mBackupUtils.executeShellCommandSync(
                LOGCAT_BUFFER_SIZE_SET_COMMAND + LOGCAT_MAX_BUFFER_SIZE);

        // Force run full backup job.
        String startLog = mLogcatInspector.mark(TAG);
        int jobId = getJobIdForUser(FULL_BACKUP_MIN_JOB_ID, profileUserId);
        mBackupUtils.executeShellCommandSync(JOB_SCHEDULER_RUN_COMMAND + " " + jobId);

        // Check logs for success.
        mLogcatInspector.assertLogcatContainsInOrder(
                LOGCAT_FILTER, TIMEOUT_FOR_FULL_BACKUP_SECONDS, startLog, FULL_BACKUP_SUCCESS_LOG);

        // Check job rescheduled.
        assertThat(isSystemJobScheduled(jobId, FULL_BACKUP_JOB_NAME)).isTrue();

        mBackupUtils.executeShellCommandSync(LOGCAT_BUFFER_SIZE_SET_COMMAND + previousBufferSize);
    }

    /** Stop the profile user and assert that the full backup job is no longer scheduled. */
    @Test
    public void testFullBackupJobCancelled() throws Exception {
        int profileUserId = mProfileUserId.get();
        int jobId = getJobIdForUser(FULL_BACKUP_MIN_JOB_ID, profileUserId);
        assertThat(isSystemJobScheduled(jobId, FULL_BACKUP_JOB_NAME)).isTrue();

        mDevice.stopUser(profileUserId, /* waitFlag */ true, /* forceFlag */ true);

        assertThat(isSystemJobScheduled(jobId, FULL_BACKUP_JOB_NAME)).isFalse();
    }

    private int getJobIdForUser(int minJobId, int userId) {
        return minJobId + userId;
    }

    /** Returns {@code true} if there is a system job scheduled with the specified parameters. */
    private boolean isSystemJobScheduled(int jobId, String jobName) throws Exception {
        // TODO: Look into making a higher level adb command or a system API for this instead.
        //  (e.g. "adb shell cmd jobscheduler is-job-scheduled system JOB-ID JOB-NAME")
        final JobSchedulerServiceDumpProto dump =
                ProtoUtils.getProto(mDevice, JobSchedulerServiceDumpProto.parser(),
                        ProtoUtils.DUMPSYS_JOB_SCHEDULER);
        for (JobSchedulerServiceDumpProto.RegisteredJob job : dump.getRegisteredJobsList()) {
            final JobStatusShortInfoProto info = job.getInfo();
            if (info.getCallingUid() == 1000 && info.getJobId() == jobId
                    && jobName.equals(info.getBatteryName())) {
                return true;
            }
        }
        return false;
    }
}
