/*
 * Copyright (C) 2017 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.internal.os;

import static android.os.BatteryStats.STATS_CURRENT;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED;

import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray;
import static com.android.internal.os.BatteryStatsImpl.TimeBase;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;

/**
 * Test class for {@link BatteryStatsImpl.LongSamplingCounterArray}.
 *
 * To run the tests, use
 *
 * runtest -c com.android.internal.os.LongSamplingCounterArrayTest frameworks-core
 *
 * or the following steps:
 *
 * Build: m FrameworksCoreTests
 * Install: adb install -r \
 *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
 * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \
 *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class LongSamplingCounterArrayTest {

    private static final long[] COUNTS = {1111, 2222, 3333, 4444};
    private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888};
    private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777};
    private static final long[] ZEROES = {0, 0, 0, 0};

    @Mock private TimeBase mTimeBase;
    private LongSamplingCounterArray mCounterArray;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mCounterArray = new LongSamplingCounterArray(mTimeBase);
        Mockito.reset(mTimeBase);
    }

    @Test
    public void testReadWriteParcel() {
        final Parcel parcel = Parcel.obtain();
        initializeCounterArrayWithDefaultValues();
        LongSamplingCounterArray.writeToParcel(parcel, mCounterArray);
        parcel.setDataPosition(0);

        // Now clear counterArray and verify values are read from parcel correctly.
        updateCounts(null, null, null);
        mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
        parcel.recycle();
    }

    @Test
    public void testReadWriteSummaryParcel() {
        final Parcel parcel = Parcel.obtain();
        initializeCounterArrayWithDefaultValues();
        LongSamplingCounterArray.writeSummaryToParcelLocked(parcel, mCounterArray);
        parcel.setDataPosition(0);

        // Now clear counterArray and verify values are read from parcel correctly.
        updateCounts(null, null, null);
        mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
        parcel.recycle();
    }

    @Test
    public void testOnTimeStarted() {
        initializeCounterArrayWithDefaultValues();
        mCounterArray.onTimeStarted(0, 0, 0);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
    }

    @Test
    public void testOnTimeStopped() {
        initializeCounterArrayWithDefaultValues();
        mCounterArray.onTimeStopped(0, 0, 0);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
    }

    @Test
    public void testGetCountsLocked() {
        initializeCounterArrayWithDefaultValues();

        when(mTimeBase.isRunning()).thenReturn(false);
        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
                "Unexpected values");
        assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
                mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
        assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
                mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");

        when(mTimeBase.isRunning()).thenReturn(true);
        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
                "Unexpected values");
        assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
                mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
        assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
                mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");
    }

    private long[] subtract(long[] val, long[] toSubtract) {
        final long[] result = val.clone();
        if (toSubtract != null) {
            for (int i = val.length - 1; i >= 0; --i) {
                result[i] -= toSubtract[i];
            }
        }
        return result;
    }

    @Test
    public void testAddCountLocked() {
        updateCounts(null, null, null);
        final long[] deltas = {123, 234, 345, 456};
        when(mTimeBase.isRunning()).thenReturn(true);
        mCounterArray.addCountLocked(deltas);
        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");

        updateCounts(null, null, null);
        mCounterArray.addCountLocked(deltas, false);
        assertArrayEquals(null, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
        mCounterArray.addCountLocked(deltas, true);
        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");

        initializeCounterArrayWithDefaultValues();
        final long[] newCounts = new long[deltas.length];
        for (int i = 0; i < deltas.length; ++i) {
            newCounts[i] = COUNTS[i] + deltas[i];
        }
        mCounterArray.addCountLocked(deltas);
        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");

        initializeCounterArrayWithDefaultValues();
        mCounterArray.addCountLocked(deltas, false);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
        mCounterArray.addCountLocked(deltas, true);
        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
    }

    @Test
    public void testReset() {
        initializeCounterArrayWithDefaultValues();
        // Test with detachIfReset=false
        mCounterArray.reset(false /* detachIfReset */);
        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
        verifyZeroInteractions(mTimeBase);

        initializeCounterArrayWithDefaultValues();
        // Test with detachIfReset=true
        mCounterArray.reset(true /* detachIfReset */);
        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
        verify(mTimeBase).remove(mCounterArray);
        verifyNoMoreInteractions(mTimeBase);
    }

    @Test
    public void testDetach() {
        mCounterArray.detach();
        verify(mTimeBase).remove(mCounterArray);
        verifyNoMoreInteractions(mTimeBase);
    }

    private void initializeCounterArrayWithDefaultValues() {
        updateCounts(COUNTS, LOADED_COUNTS, UNPLUGGED_COUNTS);
    }

    private void assertArrayEquals(long[] expected, long[] actual, String msg) {
        assertTrue(msg + ", expected: " + Arrays.toString(expected)
                + ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual));
    }

    private void updateCounts(long[] counts, long[] loadedCounts, long[] unpluggedCounts) {
        mCounterArray.mCounts = counts == null ? null : counts.clone();
        mCounterArray.mLoadedCounts = loadedCounts == null ? null : loadedCounts.clone();
        mCounterArray.mUnpluggedCounts = unpluggedCounts == null ? null : unpluggedCounts.clone();
    }
}
