/*
 * Copyright (C) 2020 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.install;

import static android.cts.install.InstallRule.VERSION_CODE_INVALID;

import static com.android.cts.install.lib.InstallUtils.getPackageInstaller;

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

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInstaller;

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 org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

@RunWith(Parameterized.class)
public final class InstallTest {
    @Parameter(0)
    public INSTALL_TYPE mInstallType;

    @Parameter(1)
    public boolean mStaged;

    @Parameter(2)
    public boolean mEnableRollback;

    @Parameters(name = "{0}_Staged{1}_Rollback{2}")
    public static Collection<Object[]> combinations() {
        boolean[] booleanValues = new boolean[]{true, false};
        List<Object[]> temp = new ArrayList<>();
        for (INSTALL_TYPE installType : INSTALL_TYPE.values()) {
            for (boolean staged : booleanValues) {
                for (boolean enableRollback : booleanValues) {
                    temp.add(new Object[]{installType, staged, enableRollback});
                }
            }
        }
        return temp;
    }

    @Rule
    public InstallRule mInstallRule = new InstallRule();

    @Rule
    public SessionRule mSessionRule = new SessionRule();

    private static final int VERSION_CODE_TARGET = 2;

    /**
     * Cleans up test environment.
     *
     * This is marked as @Test to take advantage of @Before/@After methods of hostside test cases.
     * Actual purpose of this method to be called before and after each test case of
     * {@link android.cts.install.host.InstallTest} to reduce tests flakiness.
     */
    @Test
    public void cleanUp_phase() throws Exception {
        mInstallRule.cleanUp();
        mSessionRule.cleanUp();
    }

    @Test
    public void action_phase() throws Exception {
        Install install = getParameterizedInstall(VERSION_CODE_TARGET);
        int sessionId = install.commit();
        mSessionRule.recordSessionId(sessionId);
    }

    @Test
    public void assert_commitFailure_phase() {
        Install install = getParameterizedInstall(VERSION_CODE_TARGET);
        if (mInstallType.equals(INSTALL_TYPE.SINGLE_APEX)) {
            InstallUtils.commitExpectingFailure(AssertionError.class,
                "does not support non-staged update", install);
        } else {
            InstallUtils.commitExpectingFailure(IllegalStateException.class,
                "Mix of APK and APEX is not supported for non-staged multi-package session",
                install);
        }
    }

    @Test
    public void assert_phase() {
        mInstallRule.assertPackageVersion(mInstallType, VERSION_CODE_TARGET);
    }

    @Test
    public void assert_preReboot_phase() throws Exception {
        assertNoSessionCommitBroadcastSent();
        assertThat(mSessionRule.retrieveSessionInfo().isStagedSessionReady()).isTrue();
        mInstallRule.assertPackageVersion(mInstallType, VERSION_CODE_INVALID);
    }

    @Test
    public void assert_postReboot_phase() throws Exception {
        assertThat(mSessionRule.retrieveSessionInfo().isStagedSessionApplied()).isTrue();
        mInstallRule.assertPackageVersion(mInstallType, VERSION_CODE_TARGET);
        assertNoSessionCommitBroadcastSent();
    }

    @Test
    public void action_abandonSession_phase() throws Exception {
        getPackageInstaller().abandonSession(mSessionRule.retrieveSessionId());
    }

    @Test
    public void assert_abandonSession_phase() {
        mInstallRule.assertPackageVersion(mInstallType, VERSION_CODE_INVALID);
    }

    /** Gets parameterized {@link Install} of test packages with specific version. */
    private Install getParameterizedInstall(int versionCode) {
        List<TestApp> testApps = mInstallRule.getTestApps(mInstallType, versionCode);
        Install install = testApps.size() == 1
                ? Install.single(testApps.get(0))
                : Install.multi(testApps.toArray(new TestApp[testApps.size()]));
        if (mStaged) {
            install.setStaged();
        }
        if (mEnableRollback) {
            install.setEnableRollback();
        }
        return install;
    }

    private static void assertNoSessionCommitBroadcastSent() throws InterruptedException {
        BlockingQueue<PackageInstaller.SessionInfo> committedSessions = new LinkedBlockingQueue<>();
        BroadcastReceiver sessionCommittedReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                try {
                    PackageInstaller.SessionInfo info =
                            intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
                    committedSessions.put(info);
                } catch (InterruptedException e) {
                    throw new AssertionError(e);
                }
            }
        };

        Context context = InstrumentationRegistry.getInstrumentation().getContext();
        context.registerReceiver(sessionCommittedReceiver,
                new IntentFilter(PackageInstaller.ACTION_SESSION_COMMITTED));

        PackageInstaller.SessionInfo info = committedSessions.poll(10, TimeUnit.SECONDS);
        context.unregisterReceiver(sessionCommittedReceiver);

        assertThat(info).isNull();
    }
}
