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

Commit 5c8ac126 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add read/write performance test for AppFuse."

parents c7ce678f bdee9a9a
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
LOCAL_PACKAGE_NAME := MtpDocumentsProviderPerfTests
LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
LOCAL_CERTIFICATE := media

include $(BUILD_PACKAGE)
+13 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.mtp.perftests"
    android:sharedUserId="android.media">

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.mtp"
        android:label="Performance tests for MtpDocumentsProvider." />
</manifest>
+154 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.mtp;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.system.ErrnoException;
import android.system.Os;
import android.support.test.filters.LargeTest;
import android.support.test.InstrumentationRegistry;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import libcore.io.IoUtils;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.Test;

@RunWith(JUnit4.class)
public class AppFuseTest {
    @Test
    @LargeTest
    public void testPerfReadWriteFile() throws IOException {
        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        final StorageManager storageManager = context.getSystemService(StorageManager.class);
        final int INODE = 10;
        final int SIZE = 10 * 1024 * 1024;  // 10MB
        final AppFuse appFuse = new AppFuse(
                "test",
                new TestCallback() {
                    @Override
                    public long getFileSize(int inode) throws FileNotFoundException {
                        if (inode != INODE) {
                            throw new FileNotFoundException();
                        }
                        return SIZE;
                    }

                    @Override
                    public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
                            throws IOException {
                        return size;
                    }

                    @Override
                    public int writeObjectBytes(
                            long fileHandle, int inode, long offset, int size, byte[] bytes) {
                        return size;
                    }
                });

        appFuse.mount(storageManager);

        final byte[] bytes = new byte[SIZE];
        final int SAMPLES = 100;
        final double[] readTime = new double[SAMPLES];
        final double[] writeTime = new double[SAMPLES];

        for (int i = 0; i < SAMPLES; i++) {
            final ParcelFileDescriptor fd = appFuse.openFile(
                    INODE,
                    ParcelFileDescriptor.MODE_READ_ONLY);
            try (final ParcelFileDescriptor.AutoCloseInputStream stream =
                    new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
                final long startTime = System.nanoTime();
                stream.read(bytes);
                readTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
            }

        }

        for (int i = 0; i < SAMPLES; i++) {
            final ParcelFileDescriptor fd = appFuse.openFile(
                    INODE,
                    ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE);
            try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
                    new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
                final long startTime = System.nanoTime();
                stream.write(bytes);
                writeTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
            }
        }

        appFuse.close();

        double readAverage = 0;
        double writeAverage = 0;
        double readSquaredAverage = 0;
        double writeSquaredAverage = 0;
        for (int i = 0; i < SAMPLES; i++) {
            readAverage += readTime[i];
            writeAverage += writeTime[i];
            readSquaredAverage += readTime[i] * readTime[i];
            writeSquaredAverage += writeTime[i] * writeTime[i];
        }

        readAverage /= SAMPLES;
        writeAverage /= SAMPLES;
        readSquaredAverage /= SAMPLES;
        writeSquaredAverage /= SAMPLES;

        final Bundle results = new Bundle();
        results.putDouble("readAverage", readAverage);
        results.putDouble("readStandardDeviation",
                Math.sqrt(readSquaredAverage - readAverage * readAverage));
        results.putDouble("writeAverage", writeAverage);
        results.putDouble("writeStandardDeviation",
                Math.sqrt(writeSquaredAverage - writeAverage * writeAverage));
        InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, results);
    }

    private static class TestCallback implements AppFuse.Callback {
        @Override
        public long getFileSize(int inode) throws FileNotFoundException {
            throw new FileNotFoundException();
        }

        @Override
        public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
                throws IOException {
            throw new IOException();
        }

        @Override
        public int writeObjectBytes(long fileHandle, int inode, long offset, int size, byte[] bytes)
                throws IOException {
            throw new IOException();
        }

        @Override
        public void flushFileHandle(long fileHandle) throws IOException {}

        @Override
        public void closeFileHandle(long fileHandle) {}
    }
}