Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b1bb62f authored by Misha Wagner's avatar Misha Wagner Committed by Android (Google) Code Review
Browse files

Merge "Add unit tests for ProcStatsUtil and ProcTimeInStateReader"

parents dffe0267 f268f1bd
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.annotation.Nullable;
import android.os.StrictMode;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
@@ -27,7 +29,8 @@ import java.io.IOException;
/**
 * Utility functions for reading {@code proc} files
 */
final class ProcStatsUtil {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public final class ProcStatsUtil {

    private static final String TAG = "ProcStatsUtil";

@@ -48,8 +51,9 @@ final class ProcStatsUtil {
     *
     * @param path path of the file to read
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
    @Nullable
    static String readNullSeparatedFile(String path) {
    public static String readNullSeparatedFile(String path) {
        String contents = readSingleLineProcFile(path);
        if (contents == null) {
            return null;
@@ -72,8 +76,9 @@ final class ProcStatsUtil {
     *
     * @param path path of the file to read
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
    @Nullable
    static String readSingleLineProcFile(String path) {
    public static String readSingleLineProcFile(String path) {
        return readTerminatedProcFile(path, (byte) '\n');
    }

+192 −0
Original line number Diff line number Diff line
/*
 * 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.assertEquals;

import android.content.Context;
import android.os.FileUtils;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.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.nio.file.Files;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class ProcStatsUtilTest {

    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 testReadNullSeparatedFile_empty() throws IOException {
        assertEquals(
                "",
                runReadNullSeparatedFile(""));
    }

    @Test
    public void testReadNullSeparatedFile_simple() throws IOException {
        assertEquals(
                "abc def ghi",
                runReadNullSeparatedFile("abc\0def\0ghi"));
    }

    @Test
    public void testReadNullSeparatedFile_trailingNulls() throws IOException {
        assertEquals(
                "abc",
                runReadNullSeparatedFile("abc\0\0\0\0"));
    }

    @Test
    public void testReadNullSeparatedFile_doubleNullEnds() throws IOException {
        assertEquals(
                "abc",
                runReadNullSeparatedFile("abc\0\0def"));
    }

    @Test
    public void testReadSingleLineProcFile_simple() throws IOException {
        assertEquals(
                "abc",
                runReadSingleLineProcFile("abc"));
    }

    @Test
    public void testReadSingleLineProcFile_empty() throws IOException {
        assertEquals(
                "",
                runReadSingleLineProcFile(""));
    }

    @Test
    public void testReadSingleLineProcFile_newLine() throws IOException {
        assertEquals(
                "abc",
                runReadSingleLineProcFile("abc\ndef"));
    }

    @Test
    public void testReadSingleLineProcFile_doubleNewLine() throws IOException {
        assertEquals(
                "abc",
                runReadSingleLineProcFile("abc\n\ndef"));
    }

    @Test
    public void testReadTerminatedProcFile_simple() throws IOException {
        assertEquals(
                "abc",
                runReadTerminatedProcFile("abc\0", (byte) '\0'));
    }

    @Test
    public void testReadTerminatedProcFile_withExtra() throws IOException {
        assertEquals(
                "123",
                runReadTerminatedProcFile("123\0extra", (byte) '\0'));
    }

    @Test
    public void testReadTerminatedProcFile_noTerminator() throws IOException {
        assertEquals(
                "noterm",
                runReadTerminatedProcFile("noterm", (byte) '\0'));
    }

    @Test
    public void testReadTerminatedProcFile_newLineTerm() throws IOException {
        assertEquals(
                "123",
                runReadTerminatedProcFile("123\n456", (byte) '\n'));
    }

    @Test
    public void testReadTerminatedProcFile_normalCharTerm() throws IOException {
        assertEquals(
                "abc",
                runReadTerminatedProcFile("abcdef", (byte) 'd'));
    }

    @Test
    public void testReadTerminatedProcFile_largeUnterminated() throws IOException {
        String longString = new String(new char[10000]).replace('\0', 'a');
        assertEquals(
                longString,
                runReadTerminatedProcFile(longString, (byte) '\0'));
    }

    @Test
    public void testReadTerminatedProcFile_largeTerminated() throws IOException {
        String longString = new String(new char[10000]).replace('\0', 'a');
        assertEquals(
                longString,
                runReadTerminatedProcFile(longString + "\0", (byte) '\0'));
    }

    @Test
    public void testReadTerminatedProcFile_largeExtra() throws IOException {
        String longString = new String(new char[10000]).replace('\0', 'a');
        assertEquals(
                longString,
                runReadTerminatedProcFile(longString + "\0abc", (byte) '\0'));
    }

    private String runReadNullSeparatedFile(String fileContents) throws IOException {
        File tempFile = File.createTempFile("null-separated-file", null, mProcDirectory);
        Files.write(tempFile.toPath(), fileContents.getBytes());
        String result = ProcStatsUtil.readNullSeparatedFile(tempFile.toString());
        Files.delete(tempFile.toPath());
        return result;
    }

    private String runReadSingleLineProcFile(String fileContents) throws IOException {
        File tempFile = File.createTempFile("single-line-proc-file", null, mProcDirectory);
        Files.write(tempFile.toPath(), fileContents.getBytes());
        String result = ProcStatsUtil.readSingleLineProcFile(tempFile.toString());
        Files.delete(tempFile.toPath());
        return result;
    }

    private String runReadTerminatedProcFile(
            String fileContents, byte terminator) throws IOException {
        File tempFile = File.createTempFile("terminated-proc-file", null, mProcDirectory);
        Files.write(tempFile.toPath(), fileContents.getBytes());
        String result = ProcStatsUtil.readTerminatedProcFile(tempFile.toString(), terminator);
        Files.delete(tempFile.toPath());
        return result;
    }
}
+107 −0
Original line number Diff line number Diff line
/*
 * 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.assertNull;
import static org.junit.Assert.fail;

import android.content.Context;
import android.os.FileUtils;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.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.nio.file.Files;
import java.nio.file.Path;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class ProcTimeInStateReaderTest {

    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 testSimple() throws IOException {
        Path initialTimeInStateFile = mProcDirectory.toPath().resolve("initial-time-in-state");
        Files.write(initialTimeInStateFile, "1 2\n3 4\n5 6\n7 8\n".getBytes());
        ProcTimeInStateReader reader = new ProcTimeInStateReader(initialTimeInStateFile);

        assertArrayEquals(
                "Reported frequencies are correct",
                new long[]{1, 3, 5, 7},
                reader.getFrequenciesKhz());
        assertArrayEquals(
                "Reported usage times are correct",
                new long[]{20, 40, 60, 80},
                reader.getUsageTimesMillis(initialTimeInStateFile));
    }

    @Test
    public void testDifferentFile() throws IOException {
        Path initialTimeInStateFile = mProcDirectory.toPath().resolve("initial-time-in-state");
        Files.write(initialTimeInStateFile, "1 2\n3 4\n5 6\n7 8\n".getBytes());
        ProcTimeInStateReader reader = new ProcTimeInStateReader(initialTimeInStateFile);

        Path timeInStateFile = mProcDirectory.toPath().resolve("time-in-state");
        Files.write(timeInStateFile, "1 20\n3 40\n5 60\n7 80\n".getBytes());
        assertArrayEquals(
                "Reported usage times are correct",
                new long[]{200, 400, 600, 800},
                reader.getUsageTimesMillis(timeInStateFile));
    }

    @Test
    public void testWrongLength() throws IOException {
        Path initialTimeInStateFile = mProcDirectory.toPath().resolve("initial-time-in-state");
        Files.write(initialTimeInStateFile, "1 2\n3 4\n5 6\n7 8\n".getBytes());
        ProcTimeInStateReader reader = new ProcTimeInStateReader(initialTimeInStateFile);

        Path timeInStateFile = mProcDirectory.toPath().resolve("time-in-state");
        Files.write(timeInStateFile, "1 2\n3 4\n5 6\n".getBytes());
        assertNull(reader.getUsageTimesMillis(timeInStateFile));
    }

    @Test
    public void testEmptyInitialFails() throws IOException {
        Path initialTimeInStateFile = mProcDirectory.toPath().resolve("initial-time-in-state");
        Files.write(initialTimeInStateFile, "".getBytes());
        try {
            new ProcTimeInStateReader(initialTimeInStateFile);
            fail("Instantiation didn't fail with empty initial time_in_state file");
        } catch (IOException ignored) {
        }
    }
}