/*
 * 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 com.android.server.backup.encryption.tasks;

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

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertThrows;

import android.app.Application;
import android.util.Pair;

import androidx.test.core.app.ApplicationProvider;

import com.android.server.backup.encryption.chunk.ChunkHash;
import com.android.server.backup.encryption.chunking.ProtoStore;
import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
import com.android.server.backup.encryption.keys.TertiaryKeyManager;
import com.android.server.backup.encryption.kv.KeyValueListingBuilder;
import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto;
import com.android.server.backup.encryption.protos.nano.KeyValueListingProto;
import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
import com.android.server.backup.testing.CryptoTestUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;

import javax.crypto.SecretKey;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class EncryptedKvBackupTaskTest {
    private static final boolean INCREMENTAL = true;
    private static final boolean NON_INCREMENTAL = false;

    private static final String TEST_PACKAGE_1 = "com.example.app1";
    private static final String TEST_KEY_1 = "key_1";
    private static final String TEST_KEY_2 = "key_2";
    private static final ChunkHash TEST_HASH_1 =
            new ChunkHash(Arrays.copyOf(new byte[] {1}, ChunkHash.HASH_LENGTH_BYTES));
    private static final ChunkHash TEST_HASH_2 =
            new ChunkHash(Arrays.copyOf(new byte[] {2}, ChunkHash.HASH_LENGTH_BYTES));
    private static final int TEST_LENGTH_1 = 200;
    private static final int TEST_LENGTH_2 = 300;

    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();

    @Captor private ArgumentCaptor<ChunksMetadataProto.ChunkListing> mChunkListingCaptor;

    @Mock private TertiaryKeyManager mTertiaryKeyManager;
    @Mock private RecoverableKeyStoreSecondaryKey mSecondaryKey;
    @Mock private ProtoStore<KeyValueListingProto.KeyValueListing> mKeyValueListingStore;
    @Mock private ProtoStore<ChunksMetadataProto.ChunkListing> mChunkListingStore;
    @Mock private KvBackupEncrypter mKvBackupEncrypter;
    @Mock private EncryptedBackupTask mEncryptedBackupTask;
    @Mock private SecretKey mTertiaryKey;

    private WrappedKeyProto.WrappedKey mWrappedTertiaryKey;
    private KeyValueListingProto.KeyValueListing mNewKeyValueListing;
    private ChunksMetadataProto.ChunkListing mNewChunkListing;
    private EncryptedKvBackupTask mTask;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        Application application = ApplicationProvider.getApplicationContext();
        mKeyValueListingStore = ProtoStore.createKeyValueListingStore(application);
        mChunkListingStore = ProtoStore.createChunkListingStore(application);

        mWrappedTertiaryKey = new WrappedKeyProto.WrappedKey();

        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(false);
        when(mTertiaryKeyManager.getKey()).thenReturn(mTertiaryKey);
        when(mTertiaryKeyManager.getWrappedKey()).thenReturn(mWrappedTertiaryKey);

        mNewKeyValueListing =
                createKeyValueListing(
                        CryptoTestUtils.mapOf(
                                new Pair<>(TEST_KEY_1, TEST_HASH_1),
                                new Pair<>(TEST_KEY_2, TEST_HASH_2)));
        mNewChunkListing =
                createChunkListing(
                        CryptoTestUtils.mapOf(
                                new Pair<>(TEST_HASH_1, TEST_LENGTH_1),
                                new Pair<>(TEST_HASH_2, TEST_LENGTH_2)));
        when(mKvBackupEncrypter.getNewKeyValueListing()).thenReturn(mNewKeyValueListing);
        when(mEncryptedBackupTask.performIncrementalBackup(
                        eq(mTertiaryKey), eq(mWrappedTertiaryKey), any()))
                .thenReturn(mNewChunkListing);
        when(mEncryptedBackupTask.performNonIncrementalBackup(
                        eq(mTertiaryKey), eq(mWrappedTertiaryKey), any()))
                .thenReturn(mNewChunkListing);

        mTask =
                new EncryptedKvBackupTask(
                        mTertiaryKeyManager,
                        mKeyValueListingStore,
                        mSecondaryKey,
                        mChunkListingStore,
                        mKvBackupEncrypter,
                        mEncryptedBackupTask,
                        TEST_PACKAGE_1);
    }

    @Test
    public void testPerformBackup_rotationRequired_deletesListings() throws Exception {
        mKeyValueListingStore.saveProto(
                TEST_PACKAGE_1,
                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
        mChunkListingStore.saveProto(
                TEST_PACKAGE_1,
                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));

        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(true);
        // Throw an IOException so it aborts before saving the new listings.
        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
                .thenThrow(IOException.class);

        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));

        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
    }

    @Test
    public void testPerformBackup_rotationRequiredButIncremental_throws() throws Exception {
        mKeyValueListingStore.saveProto(
                TEST_PACKAGE_1,
                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
        mChunkListingStore.saveProto(
                TEST_PACKAGE_1,
                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));

        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(true);

        assertThrows(NonIncrementalBackupRequiredException.class,
                () -> mTask.performBackup(INCREMENTAL));
    }

    @Test
    public void testPerformBackup_rotationRequiredAndNonIncremental_performsNonIncrementalBackup()
            throws Exception {
        mKeyValueListingStore.saveProto(
                TEST_PACKAGE_1,
                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
        mChunkListingStore.saveProto(
                TEST_PACKAGE_1,
                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));

        when(mTertiaryKeyManager.wasKeyRotated()).thenReturn(true);

        mTask.performBackup(NON_INCREMENTAL);

        verify(mEncryptedBackupTask)
                .performNonIncrementalBackup(eq(mTertiaryKey), eq(mWrappedTertiaryKey), any());
    }

    @Test
    public void testPerformBackup_existingStateButNonIncremental_deletesListings() throws Exception {
        mKeyValueListingStore.saveProto(
                TEST_PACKAGE_1,
                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
        mChunkListingStore.saveProto(
                TEST_PACKAGE_1,
                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));

        // Throw an IOException so it aborts before saving the new listings.
        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
                .thenThrow(IOException.class);

        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));

        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
    }

    @Test
    public void testPerformBackup_keyValueListingMissing_deletesChunkListingAndPerformsNonIncremental()
            throws Exception {
        mChunkListingStore.saveProto(
                TEST_PACKAGE_1,
                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));

        // Throw an IOException so it aborts before saving the new listings.
        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
                .thenThrow(IOException.class);

        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));

        verify(mEncryptedBackupTask).performNonIncrementalBackup(any(), any(), any());
        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
    }

    @Test
    public void testPerformBackup_chunkListingMissing_deletesKeyValueListingAndPerformsNonIncremental()
            throws Exception {
        mKeyValueListingStore.saveProto(
                TEST_PACKAGE_1,
                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));

        // Throw an IOException so it aborts before saving the new listings.
        when(mEncryptedBackupTask.performNonIncrementalBackup(any(), any(), any()))
                .thenThrow(IOException.class);

        assertThrows(IOException.class, () -> mTask.performBackup(NON_INCREMENTAL));

        verify(mEncryptedBackupTask).performNonIncrementalBackup(any(), any(), any());
        assertFalse(mKeyValueListingStore.loadProto(TEST_PACKAGE_1).isPresent());
        assertFalse(mChunkListingStore.loadProto(TEST_PACKAGE_1).isPresent());
    }

    @Test
    public void testPerformBackup_existingStateAndIncremental_performsIncrementalBackup()
            throws Exception {
        mKeyValueListingStore.saveProto(
                TEST_PACKAGE_1,
                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
        ChunksMetadataProto.ChunkListing oldChunkListing =
                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1)));
        mChunkListingStore.saveProto(TEST_PACKAGE_1, oldChunkListing);

        mTask.performBackup(INCREMENTAL);

        verify(mEncryptedBackupTask)
                .performIncrementalBackup(
                        eq(mTertiaryKey), eq(mWrappedTertiaryKey), mChunkListingCaptor.capture());
        assertChunkListingsEqual(mChunkListingCaptor.getValue(), oldChunkListing);
    }

    @Test
    public void testPerformBackup_noExistingStateAndNonIncremental_performsNonIncrementalBackup()
            throws Exception {
        mTask.performBackup(NON_INCREMENTAL);

        verify(mEncryptedBackupTask)
                .performNonIncrementalBackup(eq(mTertiaryKey), eq(mWrappedTertiaryKey), eq(null));
    }

    @Test
    public void testPerformBackup_incremental_savesNewListings() throws Exception {
        mKeyValueListingStore.saveProto(
                TEST_PACKAGE_1,
                createKeyValueListing(CryptoTestUtils.mapOf(new Pair<>(TEST_KEY_1, TEST_HASH_1))));
        mChunkListingStore.saveProto(
                TEST_PACKAGE_1,
                createChunkListing(CryptoTestUtils.mapOf(new Pair<>(TEST_HASH_1, TEST_LENGTH_1))));

        mTask.performBackup(INCREMENTAL);

        KeyValueListingProto.KeyValueListing actualKeyValueListing =
                mKeyValueListingStore.loadProto(TEST_PACKAGE_1).get();
        ChunksMetadataProto.ChunkListing actualChunkListing =
                mChunkListingStore.loadProto(TEST_PACKAGE_1).get();
        assertKeyValueListingsEqual(actualKeyValueListing, mNewKeyValueListing);
        assertChunkListingsEqual(actualChunkListing, mNewChunkListing);
    }

    @Test
    public void testPerformBackup_nonIncremental_savesNewListings() throws Exception {
        mTask.performBackup(NON_INCREMENTAL);

        KeyValueListingProto.KeyValueListing actualKeyValueListing =
                mKeyValueListingStore.loadProto(TEST_PACKAGE_1).get();
        ChunksMetadataProto.ChunkListing actualChunkListing =
                mChunkListingStore.loadProto(TEST_PACKAGE_1).get();
        assertKeyValueListingsEqual(actualKeyValueListing, mNewKeyValueListing);
        assertChunkListingsEqual(actualChunkListing, mNewChunkListing);
    }

    private static KeyValueListingProto.KeyValueListing createKeyValueListing(
            Map<String, ChunkHash> pairs) {
        return new KeyValueListingBuilder().addAll(pairs).build();
    }

    private static ChunksMetadataProto.ChunkListing createChunkListing(
            Map<ChunkHash, Integer> chunks) {
        ChunksMetadataProto.Chunk[] listingChunks = new ChunksMetadataProto.Chunk[chunks.size()];
        int chunksAdded = 0;
        for (Entry<ChunkHash, Integer> entry : chunks.entrySet()) {
            listingChunks[chunksAdded] = CryptoTestUtils.newChunk(entry.getKey(), entry.getValue());
            chunksAdded++;
        }
        return CryptoTestUtils.newChunkListingWithoutDocId(
                /* fingerprintSalt */ new byte[0],
                ChunksMetadataProto.AES_256_GCM,
                ChunksMetadataProto.CHUNK_ORDERING_TYPE_UNSPECIFIED,
                listingChunks);
    }

    private static void assertKeyValueListingsEqual(
            KeyValueListingProto.KeyValueListing actual,
            KeyValueListingProto.KeyValueListing expected) {
        KeyValueListingProto.KeyValueEntry[] actualEntries = actual.entries;
        KeyValueListingProto.KeyValueEntry[] expectedEntries = expected.entries;
        assertThat(actualEntries.length).isEqualTo(expectedEntries.length);
        for (int i = 0; i < actualEntries.length; i++) {
            assertWithMessage("entry " + i)
                    .that(actualEntries[i].key)
                    .isEqualTo(expectedEntries[i].key);
            assertWithMessage("entry " + i)
                    .that(actualEntries[i].hash)
                    .isEqualTo(expectedEntries[i].hash);
        }
    }

    private static void assertChunkListingsEqual(
            ChunksMetadataProto.ChunkListing actual, ChunksMetadataProto.ChunkListing expected) {
        ChunksMetadataProto.Chunk[] actualChunks = actual.chunks;
        ChunksMetadataProto.Chunk[] expectedChunks = expected.chunks;
        assertThat(actualChunks.length).isEqualTo(expectedChunks.length);
        for (int i = 0; i < actualChunks.length; i++) {
            assertWithMessage("chunk " + i)
                    .that(actualChunks[i].hash)
                    .isEqualTo(expectedChunks[i].hash);
            assertWithMessage("chunk " + i)
                    .that(actualChunks[i].length)
                    .isEqualTo(expectedChunks[i].length);
        }
        assertThat(actual.cipherType).isEqualTo(expected.cipherType);
        assertThat(actual.documentId)
                .isEqualTo(expected.documentId == null ? "" : expected.documentId);
    }
}
