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

Commit fafb81b7 authored by Steve McKay's avatar Steve McKay Committed by Android (Google) Code Review
Browse files

Merge "Use StubProvider for functional tests."

parents 570b6bde 0c3c6954
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target guava ub-uiautomator
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target ub-uiautomator

LOCAL_PACKAGE_NAME := DocumentsUITests
LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+101 −107
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.net.Uri;
import android.os.Parcelable;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.test.MoreAsserts;
import android.test.ServiceTestCase;
import android.test.mock.MockContentResolver;
@@ -36,6 +37,7 @@ import android.util.Log;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;

import com.google.common.collect.Lists;

import libcore.io.IoUtils;
@@ -52,70 +54,19 @@ import java.util.concurrent.TimeoutException;

public class CopyTest extends ServiceTestCase<CopyService> {

    /**
     * A test resolver that enables this test suite to listen for notifications that mark when copy
     * operations are done.
     */
    class TestContentResolver extends MockContentResolver {
        private CountDownLatch mReadySignal;
        private CountDownLatch mNotificationSignal;

        public TestContentResolver() {
            mReadySignal = new CountDownLatch(1);
        }

        /**
         * Wait for the given number of files to be copied to destination. Times out after 1 sec.
         */
        public void waitForChanges(int count) throws Exception {
            // Wait for no more than 1 second by default.
            waitForChanges(count, 1000);
        }

        /**
         * Wait for files to be copied to destination.
         *
         * @param count Number of files to wait for.
         * @param timeOut Timeout in ms. TimeoutException will be thrown if this function times out.
         */
        public void waitForChanges(int count, int timeOut) throws Exception {
            mNotificationSignal = new CountDownLatch(count);
            // Signal that the test is now waiting for files.
            mReadySignal.countDown();
            if (!mNotificationSignal.await(timeOut, TimeUnit.MILLISECONDS)) {
                throw new TimeoutException("Timed out waiting for file operations to complete.");
            }
        }

        @Override
        public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
            // Wait until the test is ready to receive file notifications.
            try {
                mReadySignal.await();
            } catch (InterruptedException e) {
                Log.d(TAG, "Interrupted while waiting for file copy readiness");
                Thread.currentThread().interrupt();
            }
            if (DocumentsContract.isDocumentUri(mContext, uri)) {
                Log.d(TAG, "Notification: " + uri);
                // Watch for document URI change notifications - this signifies the end of a copy.
                mNotificationSignal.countDown();
            }
        }
    };

    public CopyTest() {
        super(CopyService.class);
    }

    private static String AUTHORITY = "com.android.documentsui.stubprovider";
    private static String DST = "sd1";
    private static String SRC = "sd0";
    private static String SRC_ROOT = StubProvider.ROOT_0_ID;
    private static String DST_ROOT = StubProvider.ROOT_1_ID;
    private static String TAG = "CopyTest";
    private List<RootInfo> mRoots;

    private Context mContext;
    private TestContentResolver mResolver;
    private ContentProviderClient mClient;
    private DocumentsProviderHelper mDocHelper;
    private StubProvider mStorage;
    private Context mSystemContext;

@@ -129,18 +80,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
        // Reset the stub provider's storage.
        mStorage.clearCacheAndBuildRoots();

        mRoots = Lists.newArrayList();
        Uri queryUri = DocumentsContract.buildRootsUri(AUTHORITY);
        Cursor cursor = null;
        try {
            cursor = mClient.query(queryUri, null, null, null, null);
            while (cursor.moveToNext()) {
                mRoots.add(RootInfo.fromRootsCursor(AUTHORITY, cursor));
            }
        } finally {
            IoUtils.closeQuietly(cursor);
        }

        mDocHelper = new DocumentsProviderHelper(AUTHORITY, mClient);
    }

    @Override
@@ -154,7 +94,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
     */
    public void testCopyFile() throws Exception {
        String srcPath = "/test0.txt";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
        Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
                "The five boxing wizards jump quickly".getBytes());

        assertDstFileCountEquals(0);
@@ -172,7 +112,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
    public void testMoveFile() throws Exception {
        String srcPath = "/test0.txt";
        String testContent = "The five boxing wizards jump quickly";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain", testContent.getBytes());
        Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain", testContent.getBytes());

        assertDstFileCountEquals(0);

@@ -185,9 +125,9 @@ public class CopyTest extends ServiceTestCase<CopyService> {

        // Verify that one file was moved; check file contents.
        assertDstFileCountEquals(1);
        assertDoesNotExist(SRC, srcPath);
        assertDoesNotExist(SRC_ROOT, srcPath);

        byte[] dstContent = readFile(DST, srcPath);
        byte[] dstContent = readFile(DST_ROOT, srcPath);
        MoreAsserts.assertEquals("Moved file contents differ", testContent.getBytes(), dstContent);
    }

@@ -206,9 +146,9 @@ public class CopyTest extends ServiceTestCase<CopyService> {
                "/test2.txt"
        };
        List<Uri> testFiles = Lists.newArrayList(
                mStorage.createFile(SRC, srcPaths[0], "text/plain", testContent[0].getBytes()),
                mStorage.createFile(SRC, srcPaths[1], "text/plain", testContent[1].getBytes()),
                mStorage.createFile(SRC, srcPaths[2], "text/plain", testContent[2].getBytes()));
                mStorage.createFile(SRC_ROOT, srcPaths[0], "text/plain", testContent[0].getBytes()),
                mStorage.createFile(SRC_ROOT, srcPaths[1], "text/plain", testContent[1].getBytes()),
                mStorage.createFile(SRC_ROOT, srcPaths[2], "text/plain", testContent[2].getBytes()));

        assertDstFileCountEquals(0);

@@ -226,7 +166,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {

    public void testCopyEmptyDir() throws Exception {
        String srcPath = "/emptyDir";
        Uri testDir = mStorage.createFile(SRC, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
        Uri testDir = mStorage.createFile(SRC_ROOT, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
                null);

        assertDstFileCountEquals(0);
@@ -239,13 +179,13 @@ public class CopyTest extends ServiceTestCase<CopyService> {
        assertDstFileCountEquals(1);

        // Verify that the dst exists and is a directory.
        File dst = mStorage.getFile(DST, srcPath);
        File dst = mStorage.getFile(DST_ROOT, srcPath);
        assertTrue(dst.isDirectory());
    }

    public void testMoveEmptyDir() throws Exception {
        String srcPath = "/emptyDir";
        Uri testDir = mStorage.createFile(SRC, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
        Uri testDir = mStorage.createFile(SRC_ROOT, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
                null);

        assertDstFileCountEquals(0);
@@ -260,11 +200,11 @@ public class CopyTest extends ServiceTestCase<CopyService> {
        assertDstFileCountEquals(1);

        // Verify that the dst exists and is a directory.
        File dst = mStorage.getFile(DST, srcPath);
        File dst = mStorage.getFile(DST_ROOT, srcPath);
        assertTrue(dst.isDirectory());

        // Verify that the src was cleaned up.
        assertDoesNotExist(SRC, srcPath);
        assertDoesNotExist(SRC_ROOT, srcPath);
    }

    public void testMovePopulatedDir() throws Exception {
@@ -280,11 +220,11 @@ public class CopyTest extends ServiceTestCase<CopyService> {
                srcDir + "/test2.txt"
        };
        // Create test dir; put some files in it.
        Uri testDir = mStorage.createFile(SRC, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
        Uri testDir = mStorage.createFile(SRC_ROOT, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
                null);
        mStorage.createFile(SRC, srcFiles[0], "text/plain", testContent[0].getBytes());
        mStorage.createFile(SRC, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC, srcFiles[2], "text/plain", testContent[2].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());

        Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
@@ -295,24 +235,24 @@ public class CopyTest extends ServiceTestCase<CopyService> {
        mResolver.waitForChanges(11);

        // Check the content of the moved files.
        File dst = mStorage.getFile(DST, srcDir);
        File dst = mStorage.getFile(DST_ROOT, srcDir);
        assertTrue(dst.isDirectory());
        for (int i = 0; i < testContent.length; ++i) {
            byte[] dstContent = readFile(DST, srcFiles[i]);
            byte[] dstContent = readFile(DST_ROOT, srcFiles[i]);
            MoreAsserts.assertEquals("Copied file contents differ", testContent[i].getBytes(),
                    dstContent);
        }

        // Check that the src files were removed.
        assertDoesNotExist(SRC, srcDir);
        assertDoesNotExist(SRC_ROOT, srcDir);
        for (String srcFile : srcFiles) {
            assertDoesNotExist(SRC, srcFile);
            assertDoesNotExist(SRC_ROOT, srcFile);
        }
    }

    public void testCopyFileWithReadErrors() throws Exception {
        String srcPath = "/test0.txt";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
        Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
                "The five boxing wizards jump quickly".getBytes());

        assertDstFileCountEquals(0);
@@ -330,7 +270,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {

    public void testMoveFileWithReadErrors() throws Exception {
        String srcPath = "/test0.txt";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
        Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
                "The five boxing wizards jump quickly".getBytes());

        assertDstFileCountEquals(0);
@@ -352,7 +292,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
        } finally {
            // Verify that the failed copy was cleaned up, and the src file wasn't removed.
            assertDstFileCountEquals(0);
            assertExists(SRC, srcPath);
            assertExists(SRC_ROOT, srcPath);
        }
        // The asserts above didn't fail, but the CopyService did something unexpected.
        fail("Extra file operations were detected");
@@ -371,12 +311,12 @@ public class CopyTest extends ServiceTestCase<CopyService> {
                srcDir + "/test2.txt"
        };
        // Create test dir; put some files in it.
        Uri testDir = mStorage.createFile(SRC, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
        Uri testDir = mStorage.createFile(SRC_ROOT, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
                null);
        mStorage.createFile(SRC, srcFiles[0], "text/plain", testContent[0].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
        Uri errFile = mStorage
                .createFile(SRC, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC, srcFiles[2], "text/plain", testContent[2].getBytes());
                .createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());

        mStorage.simulateReadErrorsForFile(errFile);

@@ -391,22 +331,22 @@ public class CopyTest extends ServiceTestCase<CopyService> {

        // Check that both the src and dst dirs exist. The src dir shouldn't have been removed,
        // because it should contain the one errFile.
        assertTrue(mStorage.getFile(SRC, srcDir).isDirectory());
        assertTrue(mStorage.getFile(DST, srcDir).isDirectory());
        assertTrue(mStorage.getFile(SRC_ROOT, srcDir).isDirectory());
        assertTrue(mStorage.getFile(DST_ROOT, srcDir).isDirectory());

        // Check the content of the moved files.
        MoreAsserts.assertEquals("Copied file contents differ", testContent[0].getBytes(),
                readFile(DST, srcFiles[0]));
                readFile(DST_ROOT, srcFiles[0]));
        MoreAsserts.assertEquals("Copied file contents differ", testContent[2].getBytes(),
                readFile(DST, srcFiles[2]));
                readFile(DST_ROOT, srcFiles[2]));

        // Check that the src files were removed.
        assertDoesNotExist(SRC, srcFiles[0]);
        assertDoesNotExist(SRC, srcFiles[2]);
        assertDoesNotExist(SRC_ROOT, srcFiles[0]);
        assertDoesNotExist(SRC_ROOT, srcFiles[2]);

        // Check that the error file was not copied over.
        assertDoesNotExist(DST, srcFiles[1]);
        assertExists(SRC, srcFiles[1]);
        assertDoesNotExist(DST_ROOT, srcFiles[1]);
        assertExists(SRC_ROOT, srcFiles[1]);
    }

    /**
@@ -414,13 +354,14 @@ public class CopyTest extends ServiceTestCase<CopyService> {
     *
     * @throws FileNotFoundException
     */
    private Intent createCopyIntent(List<Uri> srcs) throws FileNotFoundException {
    private Intent createCopyIntent(List<Uri> srcs) throws Exception {
        final ArrayList<DocumentInfo> srcDocs = Lists.newArrayList();
        for (Uri src : srcs) {
            srcDocs.add(DocumentInfo.fromUri(mResolver, src));
        }

        final Uri dst = DocumentsContract.buildDocumentUri(AUTHORITY, mRoots.get(1).documentId);
        RootInfo root = mDocHelper.getRoot(DST_ROOT);
        final Uri dst = DocumentsContract.buildDocumentUri(AUTHORITY, root.documentId);
        DocumentStack stack = new DocumentStack();
        stack.push(DocumentInfo.fromUri(mResolver, dst));
        final Intent copyIntent = new Intent(mContext, CopyService.class);
@@ -435,8 +376,9 @@ public class CopyTest extends ServiceTestCase<CopyService> {
     * Returns a count of the files in the given directory.
     */
    private void assertDstFileCountEquals(int expected) throws RemoteException {
        RootInfo dest = mDocHelper.getRoot(DST_ROOT);
        final Uri queryUri = DocumentsContract.buildChildDocumentsUri(AUTHORITY,
                mRoots.get(1).documentId);
                dest.documentId);
        Cursor c = null;
        int count = 0;
        try {
@@ -474,8 +416,8 @@ public class CopyTest extends ServiceTestCase<CopyService> {
    }

    private void assertCopied(String path) throws Exception {
        MoreAsserts.assertEquals("Copied file contents differ", readFile(SRC, path),
                readFile(DST, path));
        MoreAsserts.assertEquals("Copied file contents differ", readFile(SRC_ROOT, path),
                readFile(DST_ROOT, path));
    }

    /**
@@ -509,4 +451,56 @@ public class CopyTest extends ServiceTestCase<CopyService> {
        mStorage.attachInfo(mContext, info);
        mResolver.addProvider(AUTHORITY, mStorage);
    }

    /**
     * A test resolver that enables this test suite to listen for notifications that mark when copy
     * operations are done.
     */
    class TestContentResolver extends MockContentResolver {
        private CountDownLatch mReadySignal;
        private CountDownLatch mNotificationSignal;

        public TestContentResolver() {
            mReadySignal = new CountDownLatch(1);
        }

        /**
         * Wait for the given number of files to be copied to destination. Times out after 1 sec.
         */
        public void waitForChanges(int count) throws Exception {
            // Wait for no more than 1 second by default.
            waitForChanges(count, 1000);
        }

        /**
         * Wait for files to be copied to destination.
         *
         * @param count Number of files to wait for.
         * @param timeOut Timeout in ms. TimeoutException will be thrown if this function times out.
         */
        public void waitForChanges(int count, int timeOut) throws Exception {
            mNotificationSignal = new CountDownLatch(count);
            // Signal that the test is now waiting for files.
            mReadySignal.countDown();
            if (!mNotificationSignal.await(timeOut, TimeUnit.MILLISECONDS)) {
                throw new TimeoutException("Timed out waiting for file operations to complete.");
            }
        }

        @Override
        public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
            // Wait until the test is ready to receive file notifications.
            try {
                mReadySignal.await();
            } catch (InterruptedException e) {
                Log.d(TAG, "Interrupted while waiting for file copy readiness");
                Thread.currentThread().interrupt();
            }
            if (DocumentsContract.isDocumentUri(mContext, uri)) {
                Log.d(TAG, "Notification: " + uri);
                // Watch for document URI change notifications - this signifies the end of a copy.
                mNotificationSignal.countDown();
            }
        }
    };
}
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.documentsui;

import static com.android.documentsui.model.DocumentInfo.getCursorString;

import android.content.ContentProviderClient;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;

import com.android.documentsui.model.RootInfo;

import libcore.io.IoUtils;

/**
 * Provides support for creation of documents in a test settings.
 */
public class DocumentsProviderHelper {

    private final ContentProviderClient mClient;
    private final String mAuthority;

    public DocumentsProviderHelper(String authority, ContentProviderClient client) {
        mClient = client;
        mAuthority = authority;
    }

    public RootInfo getRoot(String id) throws RemoteException {
        final Uri rootsUri = DocumentsContract.buildRootsUri(mAuthority);

        Cursor cursor = null;
        try {
            cursor = mClient.query(rootsUri, null, null, null, null);
            while (cursor.moveToNext()) {
                if (id.equals(getCursorString(cursor, Root.COLUMN_ROOT_ID))) {
                    return RootInfo.fromRootsCursor(mAuthority, cursor);
                }
            }
            throw new IllegalArgumentException("Can't find matching root for id=" + id);
        } catch (Exception e) {
            throw new RuntimeException("Can't load root for id=" + id , e);
        } finally {
            IoUtils.closeQuietly(cursor);
        }
    }

    public Uri createDocument(Uri parentUri, String mimeType, String name) {
        if (name.contains("/")) {
            throw new IllegalArgumentException("Name and mimetype probably interposed.");
        }
        try {
            return DocumentsContract.createDocument(mClient, parentUri, mimeType, name);
        } catch (RemoteException e) {
            throw new RuntimeException("Couldn't create document: " + name + " with mimetype " + mimeType, e);
        }
    }

    public Uri createFolder(Uri parentUri, String name) {
        return createDocument(parentUri, Document.MIME_TYPE_DIR, name);
    }

    public Uri createDocument(RootInfo root, String mimeType, String name) {
        Uri rootUri = DocumentsContract.buildDocumentUri(mAuthority, root.documentId);
        return createDocument(rootUri, mimeType, name);
    }

    public Uri createFolder(RootInfo root, String name) {
        return createDocument(root, Document.MIME_TYPE_DIR, name);
    }
}
+115 −40

File changed.

Preview size limit exceeded, changes collapsed.

+63 −37

File changed.

Preview size limit exceeded, changes collapsed.

Loading