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

Commit f268f1bd authored by Misha Wagner's avatar Misha Wagner
Browse files

Add unit tests for ProcStatsUtil and ProcTimeInStateReader

Test: This is a test

Change-Id: I5d3b7150414572c7ffcdc891a13234ed2cf3e0e7
parent 5a51e004
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) {
        }
    }
}