/*
 * Copyright (C) 2018 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 org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.testng.Assert.assertThrows;

import android.content.Context;
import android.os.FileUtils;
import android.platform.test.annotations.Presubmit;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

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

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Predicate;

@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KernelCpuThreadReaderTest {
    private File mProcDirectory;

    @Before
    public void setUp() {
        Context context = InstrumentationRegistry.getContext();
        mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE);
    }

    @After
    public void tearDown() throws Exception {
        FileUtils.deleteContents(mProcDirectory);
    }

    @Test
    public void testReader_byUids() throws IOException {
        int[] uids = new int[]{0, 2, 3, 4, 5, 6000};
        Predicate<Integer> uidPredicate = uid -> uid == 0 || uid >= 4;
        int[] expectedUids = new int[]{0, 4, 5, 6000};
        KernelCpuThreadReader.Injector processUtils =
                new KernelCpuThreadReader.Injector() {
                    @Override
                    public int getUidForPid(int pid) {
                        return pid;
                    }
                };

        for (int uid : uids) {
            setupDirectory(mProcDirectory.toPath().resolve(String.valueOf(uid)),
                    new int[]{uid * 10},
                    "process" + uid, new String[]{"thread" + uid}, new int[]{1000},
                    new int[][]{{uid}});
        }
        final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader(
                8,
                uidPredicate,
                mProcDirectory.toPath(),
                mProcDirectory.toPath().resolve(uids[0] + "/task/" + uids[0] + "/time_in_state"),
                processUtils);
        ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsageByUids =
                kernelCpuThreadReader.getProcessCpuUsage();
        processCpuUsageByUids.sort(Comparator.comparing(usage -> usage.processId));

        assertEquals(expectedUids.length, processCpuUsageByUids.size());
        for (int i = 0; i < expectedUids.length; i++) {
            KernelCpuThreadReader.ProcessCpuUsage processCpuUsage =
                    processCpuUsageByUids.get(i);
            int uid = expectedUids[i];
            checkResults(processCpuUsage, kernelCpuThreadReader.getCpuFrequenciesKhz(),
                    uid, uid, new int[]{uid * 10}, "process" + uid, new String[]{"thread" + uid},
                    new int[]{1000}, new int[][]{{uid}});
        }
    }

    private void setupDirectory(Path processPath, int[] threadIds, String processName,
            String[] threadNames, int[] cpuFrequencies, int[][] cpuTimes) throws IOException {
        // Make /proc/$PID
        assertTrue(processPath.toFile().mkdirs());

        // Make /proc/$PID/task
        final Path selfThreadsPath = processPath.resolve("task");
        assertTrue(selfThreadsPath.toFile().mkdirs());

        // Make /proc/$PID/cmdline
        Files.write(processPath.resolve("cmdline"), processName.getBytes());

        // Make thread directories in reverse order, as they are read in order of creation by
        // CpuThreadProcReader
        for (int i = 0; i < threadIds.length; i++) {
            // Make /proc/$PID/task/$TID
            final Path threadPath = selfThreadsPath.resolve(String.valueOf(threadIds[i]));
            assertTrue(threadPath.toFile().mkdirs());

            // Make /proc/$PID/task/$TID/comm
            Files.write(threadPath.resolve("comm"), threadNames[i].getBytes());

            // Make /proc/$PID/task/$TID/time_in_state
            final OutputStream timeInStateStream =
                    Files.newOutputStream(threadPath.resolve("time_in_state"));
            for (int j = 0; j < cpuFrequencies.length; j++) {
                final String line = cpuFrequencies[j] + " " + cpuTimes[i][j] + "\n";
                timeInStateStream.write(line.getBytes());
            }
            timeInStateStream.close();
        }
    }

    private void checkResults(KernelCpuThreadReader.ProcessCpuUsage processCpuUsage,
            int[] readerCpuFrequencies, int uid, int processId, int[] threadIds, String processName,
            String[] threadNames, int[] cpuFrequencies, int[][] cpuTimes) {
        assertNotNull(processCpuUsage);
        assertEquals(processId, processCpuUsage.processId);
        assertEquals(uid, processCpuUsage.uid);
        assertEquals(processName, processCpuUsage.processName);
        assertEquals(threadIds.length, processCpuUsage.threadCpuUsages.size());

        // Sort the thread CPU usages to compare with test case
        final ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages =
                new ArrayList<>(processCpuUsage.threadCpuUsages);
        threadCpuUsages.sort(Comparator.comparingInt(a -> a.threadId));

        int threadCount = 0;
        for (KernelCpuThreadReader.ThreadCpuUsage threadCpuUsage : threadCpuUsages) {
            assertEquals(threadIds[threadCount], threadCpuUsage.threadId);
            assertEquals(threadNames[threadCount], threadCpuUsage.threadName);

            for (int i = 0; i < threadCpuUsage.usageTimesMillis.length; i++) {
                assertEquals(
                        cpuTimes[threadCount][i] * 10,
                        threadCpuUsage.usageTimesMillis[i]);
                assertEquals(
                        cpuFrequencies[i],
                        readerCpuFrequencies[i]);
            }
            threadCount++;
        }

        assertEquals(threadCount, threadIds.length);
    }

    @Test
    public void testBucketSetup_simple() {
        long[] frequencies = {1, 2, 3, 4, 1, 2, 3, 4};
        KernelCpuThreadReader.FrequencyBucketCreator
                frequencyBucketCreator = new KernelCpuThreadReader.FrequencyBucketCreator(
                frequencies, 4);
        assertArrayEquals(
                new int[]{1, 3, 1, 3},
                frequencyBucketCreator.getBucketMinFrequencies(frequencies));
        assertArrayEquals(
                new int[]{2, 2, 2, 2},
                frequencyBucketCreator.getBucketedValues(new long[]{1, 1, 1, 1, 1, 1, 1, 1}));
    }

    @Test
    public void testBucketSetup_noBig() {
        long[] frequencies = {1, 2, 3, 4, 5, 6, 7, 8};
        KernelCpuThreadReader.FrequencyBucketCreator
                frequencyBucketCreator = new KernelCpuThreadReader.FrequencyBucketCreator(
                frequencies, 4);
        assertArrayEquals(
                new int[]{1, 3, 5, 7},
                frequencyBucketCreator.getBucketMinFrequencies(frequencies));
        assertArrayEquals(
                new int[]{2, 2, 2, 2},
                frequencyBucketCreator.getBucketedValues(new long[]{1, 1, 1, 1, 1, 1, 1, 1}));
    }

    @Test
    public void testBucketSetup_moreLittle() {
        long[] frequencies = {1, 2, 3, 4, 5, 1, 2, 3};
        KernelCpuThreadReader.FrequencyBucketCreator
                frequencyBucketCreator = new KernelCpuThreadReader.FrequencyBucketCreator(
                frequencies, 4);
        assertArrayEquals(
                new int[]{1, 3, 1, 2},
                frequencyBucketCreator.getBucketMinFrequencies(frequencies));
        assertArrayEquals(
                new int[]{2, 3, 1, 2},
                frequencyBucketCreator.getBucketedValues(new long[]{1, 1, 1, 1, 1, 1, 1, 1}));
    }

    @Test
    public void testBucketSetup_moreBig() {
        long[] frequencies = {1, 2, 3, 1, 2, 3, 4, 5};
        KernelCpuThreadReader.FrequencyBucketCreator
                frequencyBucketCreator = new KernelCpuThreadReader.FrequencyBucketCreator(
                frequencies, 4);
        assertArrayEquals(
                new int[]{1, 2, 1, 3},
                frequencyBucketCreator.getBucketMinFrequencies(frequencies));
        assertArrayEquals(
                new int[]{1, 2, 2, 3},
                frequencyBucketCreator.getBucketedValues(new long[]{1, 1, 1, 1, 1, 1, 1, 1}));
    }

    @Test
    public void testBucketSetup_equalBuckets() {
        long[] frequencies = {1, 2, 3, 4, 1, 2, 3, 4};
        KernelCpuThreadReader.FrequencyBucketCreator
                frequencyBucketCreator = new KernelCpuThreadReader.FrequencyBucketCreator(
                frequencies, 8);
        assertArrayEquals(
                new int[]{1, 2, 3, 4, 1, 2, 3, 4},
                frequencyBucketCreator.getBucketMinFrequencies(frequencies));
        assertArrayEquals(
                new int[]{1, 1, 1, 1, 1, 1, 1, 1},
                frequencyBucketCreator.getBucketedValues(new long[]{1, 1, 1, 1, 1, 1, 1, 1}));
    }

    @Test
    public void testBucketSetup_moreBigBucketsThanFrequencies() {
        long[] frequencies = {1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3};
        KernelCpuThreadReader.FrequencyBucketCreator
                frequencyBucketCreator = new KernelCpuThreadReader.FrequencyBucketCreator(
                frequencies, 8);
        assertArrayEquals(
                new int[]{1, 3, 5, 7, 1, 2, 3},
                frequencyBucketCreator.getBucketMinFrequencies(frequencies));
        assertArrayEquals(
                new int[]{2, 2, 2, 3, 1, 1, 1},
                frequencyBucketCreator.getBucketedValues(
                        new long[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}));
    }

    @Test
    public void testBucketSetup_oneBucket() {
        long[] frequencies = {1, 2, 3, 4, 2, 3, 4, 5};
        KernelCpuThreadReader.FrequencyBucketCreator
                frequencyBucketCreator = new KernelCpuThreadReader.FrequencyBucketCreator(
                frequencies, 1);
        assertArrayEquals(
                new int[]{1},
                frequencyBucketCreator.getBucketMinFrequencies(frequencies));
        assertArrayEquals(
                new int[]{8},
                frequencyBucketCreator.getBucketedValues(
                        new long[]{1, 1, 1, 1, 1, 1, 1, 1}));
    }

    @Test
    public void testGetBigFrequenciesStartIndex_simple() {
        assertEquals(
                3, KernelCpuThreadReader.FrequencyBucketCreator.getBigFrequenciesStartIndex(
                        new long[]{1, 2, 3, 1, 2, 3}));
    }

    @Test
    public void testGetBigFrequenciesStartIndex_moreLittle() {
        assertEquals(
                4, KernelCpuThreadReader.FrequencyBucketCreator.getBigFrequenciesStartIndex(
                        new long[]{1, 2, 3, 4, 1, 2}));
    }

    @Test
    public void testGetBigFrequenciesStartIndex_moreBig() {
        assertEquals(
                2, KernelCpuThreadReader.FrequencyBucketCreator.getBigFrequenciesStartIndex(
                        new long[]{1, 2, 1, 2, 3, 4}));
    }

    @Test
    public void testGetBigFrequenciesStartIndex_noBig() {
        assertEquals(
                4, KernelCpuThreadReader.FrequencyBucketCreator.getBigFrequenciesStartIndex(
                        new long[]{1, 2, 3, 4}));
    }

    @Test
    public void testUidPredicate_singleRange() {
        KernelCpuThreadReaderSettingsObserver.UidPredicate uidPredicate =
                KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("1000-1999");
        assertTrue(uidPredicate.test(1000));
        assertTrue(uidPredicate.test(1050));
        assertTrue(uidPredicate.test(1999));
        assertFalse(uidPredicate.test(2000));
        assertFalse(uidPredicate.test(0));
        assertFalse(uidPredicate.test(10000));
        assertFalse(uidPredicate.test(-100));
    }

    @Test
    public void testUidPredicate_singleUid() {
        KernelCpuThreadReaderSettingsObserver.UidPredicate uidPredicate =
                KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("1234-1234");
        assertTrue(uidPredicate.test(1234));
        assertFalse(uidPredicate.test(1235));
        assertFalse(uidPredicate.test(1232));
        assertFalse(uidPredicate.test(0));
        assertFalse(uidPredicate.test(-1234));
    }

    @Test
    public void testUidPredicate_uidAndRange() {
        KernelCpuThreadReaderSettingsObserver.UidPredicate uidPredicate =
                KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString(
                        "1000-1000;1050-1060");
        assertTrue(uidPredicate.test(1000));
        assertTrue(uidPredicate.test(1050));
        assertTrue(uidPredicate.test(1054));
        assertTrue(uidPredicate.test(1060));
        assertFalse(uidPredicate.test(1040));
        assertFalse(uidPredicate.test(1001));
        assertFalse(uidPredicate.test(0));
        assertFalse(uidPredicate.test(-1000));
    }

    @Test
    public void testUidPredicate_multiple() {
        KernelCpuThreadReaderSettingsObserver.UidPredicate uidPredicate =
                KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString(
                        "1000-1000;1050-1060;1001-1001;2000-3000");
        assertTrue(uidPredicate.test(1000));
        assertTrue(uidPredicate.test(1001));
        assertTrue(uidPredicate.test(1050));
        assertTrue(uidPredicate.test(1054));
        assertTrue(uidPredicate.test(1060));
        assertTrue(uidPredicate.test(1001));
        assertTrue(uidPredicate.test(2000));
        assertTrue(uidPredicate.test(2444));
        assertTrue(uidPredicate.test(3000));
        assertFalse(uidPredicate.test(0));
        assertFalse(uidPredicate.test(1040));
        assertFalse(uidPredicate.test(3001));
        assertFalse(uidPredicate.test(1999));
    }

    @Test
    public void testUidPredicate_zero() {
        KernelCpuThreadReaderSettingsObserver.UidPredicate uidPredicate =
                KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("0-0");
        assertTrue(uidPredicate.test(0));
        assertFalse(uidPredicate.test(1));
        assertFalse(uidPredicate.test(2000));
        assertFalse(uidPredicate.test(10000));
        assertFalse(uidPredicate.test(-100));
    }

    @Test
    public void testUidPredicate_emptyRangeString() {
        assertThrows(
                NumberFormatException.class,
                () -> KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString(""));
    }

    @Test
    public void testUidPredicate_singleNumber() {
        assertThrows(
                NumberFormatException.class,
                () -> KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("1000"));
    }

    @Test
    public void testUidPredicate_lettersInRange() {
        assertThrows(
                NumberFormatException.class,
                () -> KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString(
                        "0-0;1-1;a;3-3"));
    }

    @Test
    public void testUidPredicate_onlyLetters() {
        assertThrows(
                NumberFormatException.class,
                () -> KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("abc"));
    }

    @Test
    public void testUidPredicate_backwardsRange() {
        assertThrows(
                IllegalArgumentException.class,
                () -> KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("20-10"));
    }

    @Test
    public void testUidPredicate_comma() {
        assertThrows(
                NumberFormatException.class,
                () -> KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("1-1,2-2,3-3"));
    }
}
