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

Commit f65fdebd authored by Tomasz Mikolajewski's avatar Tomasz Mikolajewski
Browse files

Add tests for copying virtual typed files.

Bug: 26147488
Change-Id: I44cfae518f4b6dfceed5b9f50b132e2acf161b3f
parent cca31ebb
Loading
Loading
Loading
Loading
+9 −2
Original line number Original line Diff line number Diff line
@@ -501,16 +501,23 @@ public class CopyService extends IntentService {


        // If the file is virtual, but can be converted to another format, then try to copy it
        // If the file is virtual, but can be converted to another format, then try to copy it
        // as such format. Also, append an extension for the target mime type (if known).
        // as such format. Also, append an extension for the target mime type (if known).
        if (srcInfo.isVirtualDocument() && srcInfo.isTypedDocument()) {
        if (srcInfo.isVirtualDocument()) {
            if (!srcInfo.isTypedDocument()) {
                // Impossible to copy a file which is virtual, but not typed.
                mFailedFiles.add(srcInfo);
                return false;
            }
            final String[] streamTypes = getContentResolver().getStreamTypes(
            final String[] streamTypes = getContentResolver().getStreamTypes(
                    srcInfo.derivedUri, "*/*");
                    srcInfo.derivedUri, "*/*");
            if (streamTypes.length > 0) {
            if (streamTypes != null && streamTypes.length > 0) {
                dstMimeType = streamTypes[0];
                dstMimeType = streamTypes[0];
                final String extension = MimeTypeMap.getSingleton().
                final String extension = MimeTypeMap.getSingleton().
                        getExtensionFromMimeType(dstMimeType);
                        getExtensionFromMimeType(dstMimeType);
                dstDisplayName = srcInfo.displayName +
                dstDisplayName = srcInfo.displayName +
                        (extension != null ? "." + extension : srcInfo.displayName);
                        (extension != null ? "." + extension : srcInfo.displayName);
            } else {
            } else {
                // The provider says that it supports typed documents, but doesn't say
                // anything about available formats.
                // TODO: Log failures. b/26192412
                // TODO: Log failures. b/26192412
                mFailedFiles.add(srcInfo);
                mFailedFiles.add(srcInfo);
                return false;
                return false;
+58 −15
Original line number Original line Diff line number Diff line
@@ -97,7 +97,7 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {


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


        startService(createCopyIntent(Lists.newArrayList(testFile)));
        startService(createCopyIntent(Lists.newArrayList(testFile)));
@@ -110,10 +110,33 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {
        assertCopied(srcPath);
        assertCopied(srcPath);
    }
    }


    public void testCopyVirtualTypedFile() throws Exception {
        String srcPath = "/virtual.sth";
        String expectedDstPath = "/virtual.sth.pdf";
        ArrayList<String> streamTypes = new ArrayList<>();
        streamTypes.add("application/pdf");
        streamTypes.add("text/html");
        String testContent = "I love fruit cakes!";
        Uri testFile = mStorage.createVirtualFile(SRC_ROOT, srcPath, "virtual/mime-type",
                streamTypes, testContent.getBytes());

        startService(createCopyIntent(Lists.newArrayList(testFile)));

        // 2 operations: file creation, then writing data.
        mResolver.waitForChanges(2);

        // Verify that one file was copied.
        assertDestFileCount(1);

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

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


        Intent moveIntent = createCopyIntent(Lists.newArrayList(testFile));
        Intent moveIntent = createCopyIntent(Lists.newArrayList(testFile));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
@@ -142,9 +165,12 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {
                "/test2.txt"
                "/test2.txt"
        };
        };
        List<Uri> testFiles = Lists.newArrayList(
        List<Uri> testFiles = Lists.newArrayList(
                mStorage.createFile(SRC_ROOT, srcPaths[0], "text/plain", testContent[0].getBytes()),
                mStorage.createRegularFile(SRC_ROOT, srcPaths[0], "text/plain",
                mStorage.createFile(SRC_ROOT, srcPaths[1], "text/plain", testContent[1].getBytes()),
                        testContent[0].getBytes()),
                mStorage.createFile(SRC_ROOT, srcPaths[2], "text/plain", testContent[2].getBytes()));
                mStorage.createRegularFile(SRC_ROOT, srcPaths[1], "text/plain",
                        testContent[1].getBytes()),
                mStorage.createRegularFile(SRC_ROOT, srcPaths[2], "text/plain",
                        testContent[2].getBytes()));


        // Copy all the test files.
        // Copy all the test files.
        startService(createCopyIntent(testFiles));
        startService(createCopyIntent(testFiles));
@@ -195,7 +221,6 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {


        Intent intent = createCopyIntent(Lists.newArrayList(testDir), descDir);
        Intent intent = createCopyIntent(Lists.newArrayList(testDir), descDir);
        startService(intent);
        startService(intent);

        getService().addFinishedListener(mListener);
        getService().addFinishedListener(mListener);


        mListener.waitForFinished();
        mListener.waitForFinished();
@@ -240,9 +265,9 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {
        };
        };
        // Create test dir; put some files in it.
        // Create test dir; put some files in it.
        Uri testDir = createTestDirectory(srcDir);
        Uri testDir = createTestDirectory(srcDir);
        mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
        mStorage.createRegularFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createRegularFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
        mStorage.createRegularFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());


        Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
        Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
@@ -270,7 +295,7 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {


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


        mStorage.simulateReadErrorsForFile(testFile);
        mStorage.simulateReadErrorsForFile(testFile);
@@ -284,9 +309,26 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {
        assertDestFileCount(0);
        assertDestFileCount(0);
    }
    }


    public void testCopyVirtualNonTypedFile() throws Exception {
        String srcPath = "/non-typed.sth";
        // Empty stream types causes the FLAG_SUPPORTS_TYPED_DOCUMENT to be not set.
        ArrayList<String> streamTypes = new ArrayList<>();
        Uri testFile = mStorage.createVirtualFile(SRC_ROOT, srcPath, "virtual/mime-type",
                streamTypes, "I love Tokyo!".getBytes());

        Intent intent = createCopyIntent(Lists.newArrayList(testFile));
        startService(intent);
        getService().addFinishedListener(mListener);

        mListener.waitForFinished();
        mListener.assertFailedCount(1);
        mListener.assertFileFailed("non-typed.sth");
        assertDestFileCount(0);
    }

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


        mStorage.simulateReadErrorsForFile(testFile);
        mStorage.simulateReadErrorsForFile(testFile);
@@ -326,10 +368,10 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {
        };
        };
        // Create test dir; put some files in it.
        // Create test dir; put some files in it.
        Uri testDir = createTestDirectory(srcDir);
        Uri testDir = createTestDirectory(srcDir);
        mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
        mStorage.createRegularFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
        Uri errFile = mStorage
        Uri errFile = mStorage
                .createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
                .createRegularFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
        mStorage.createRegularFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());


        mStorage.simulateReadErrorsForFile(errFile);
        mStorage.simulateReadErrorsForFile(errFile);


@@ -363,7 +405,7 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {
    }
    }


    private Uri createTestDirectory(String dir) throws IOException {
    private Uri createTestDirectory(String dir) throws IOException {
        return mStorage.createFile(
        return mStorage.createRegularFile(
                SRC_ROOT, dir, DocumentsContract.Document.MIME_TYPE_DIR, null);
                SRC_ROOT, dir, DocumentsContract.Document.MIME_TYPE_DIR, null);
    }
    }


@@ -473,6 +515,7 @@ public class CopyServiceTest extends ServiceTestCase<CopyService> {


        final CountDownLatch latch = new CountDownLatch(1);
        final CountDownLatch latch = new CountDownLatch(1);
        final List<DocumentInfo> failedDocs = new ArrayList<>();
        final List<DocumentInfo> failedDocs = new ArrayList<>();

        @Override
        @Override
        public void onFinished(List<DocumentInfo> failed) {
        public void onFinished(List<DocumentInfo> failed) {
            failedDocs.addAll(failed);
            failedDocs.addAll(failed);
+50 −17
Original line number Original line Diff line number Diff line
@@ -324,11 +324,11 @@ public class StubProvider extends DocumentsProvider {
        }
        }
        for (final String mimeType : document.streamTypes) {
        for (final String mimeType : document.streamTypes) {
            // Strict compare won't accept wildcards, but that's OK for tests, as DocumentsUI
            // Strict compare won't accept wildcards, but that's OK for tests, as DocumentsUI
            // doesn't use them for openTypedDocument.
            // doesn't use them for getStreamTypes nor openTypedDocument.
            if (mimeType.equals(mimeTypeFilter)) {
            if (mimeType.equals(mimeTypeFilter)) {
                ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
                ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
                            document.file, ParcelFileDescriptor.MODE_READ_ONLY);
                            document.file, ParcelFileDescriptor.MODE_READ_ONLY);
                if (!documentId.equals(mSimulateReadErrors)) {
                if (documentId.equals(mSimulateReadErrors)) {
                    pfd = new ParcelFileDescriptor(pfd) {
                    pfd = new ParcelFileDescriptor(pfd) {
                        @Override
                        @Override
                        public void checkError() throws IOException {
                        public void checkError() throws IOException {
@@ -342,6 +342,23 @@ public class StubProvider extends DocumentsProvider {
        throw new IllegalArgumentException("Invalid MIME type filter for openTypedDocument().");
        throw new IllegalArgumentException("Invalid MIME type filter for openTypedDocument().");
    }
    }


    @Override
    public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
        final StubDocument document = mStorage.get(DocumentsContract.getDocumentId(uri));
        if (document == null) {
            throw new IllegalArgumentException(
                    "The provided Uri is incorrect, or the file is gone.");
        }
        if ((document.flags & Document.FLAG_SUPPORTS_TYPED_DOCUMENT) == 0) {
            return null;
        }
        if (!"*/*".equals(mimeTypeFilter)) {
            // Not used by DocumentsUI, so don't bother implementing it.
            throw new UnsupportedOperationException();
        }
        return document.streamTypes.toArray(new String[document.streamTypes.size()]);
    }

    private ParcelFileDescriptor startWrite(final StubDocument document)
    private ParcelFileDescriptor startWrite(final StubDocument document)
            throws FileNotFoundException {
            throws FileNotFoundException {
        ParcelFileDescriptor[] pipe;
        ParcelFileDescriptor[] pipe;
@@ -476,23 +493,14 @@ public class StubProvider extends DocumentsProvider {
    }
    }


    @VisibleForTesting
    @VisibleForTesting
    public Uri createFile(String rootId, String path, String mimeType, byte[] content)
    public File createFile(String rootId, String path, String mimeType, byte[] content)
            throws FileNotFoundException, IOException {
            throws FileNotFoundException, IOException {
        Log.d(TAG, "Creating test file " + rootId + ":" + path);
        Log.d(TAG, "Creating test file " + rootId + ":" + path);
        StubDocument root = mRoots.get(rootId).document;
        StubDocument root = mRoots.get(rootId).document;
        if (root == null) {
        if (root == null) {
            throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
            throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
        }
        }
        File file = new File(root.file, path.substring(1));
        final File file = new File(root.file, path.substring(1));
        StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
        if (parent == null) {
            parent = mStorage.get(createFile(rootId, file.getParentFile().getPath(),
                    DocumentsContract.Document.MIME_TYPE_DIR, null));
            Log.d(TAG, "Created parent " + parent.documentId);
        } else {
            Log.d(TAG, "Found parent " + parent.documentId);
        }

        if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
        if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
            if (!file.mkdirs()) {
            if (!file.mkdirs()) {
                throw new FileNotFoundException("Couldn't create directory " + file.getPath());
                throw new FileNotFoundException("Couldn't create directory " + file.getPath());
@@ -501,16 +509,41 @@ public class StubProvider extends DocumentsProvider {
            if (!file.createNewFile()) {
            if (!file.createNewFile()) {
                throw new FileNotFoundException("Couldn't create file " + file.getPath());
                throw new FileNotFoundException("Couldn't create file " + file.getPath());
            }
            }
            // Add content to the file.
            try (final FileOutputStream fout = new FileOutputStream(file)) {
            FileOutputStream fout = new FileOutputStream(file);
                fout.write(content);
                fout.write(content);
            fout.close();
            }
        }
        return file;
    }

    @VisibleForTesting
    public Uri createRegularFile(String rootId, String path, String mimeType, byte[] content)
            throws FileNotFoundException, IOException {
        final File file = createFile(rootId, path, mimeType, content);
        final StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
        if (parent == null) {
            throw new FileNotFoundException("Parent not found.");
        }
        }
        final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
        final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
        mStorage.put(document.documentId, document);
        mStorage.put(document.documentId, document);
        return DocumentsContract.buildDocumentUri(mAuthority,  document.documentId);
        return DocumentsContract.buildDocumentUri(mAuthority,  document.documentId);
    }
    }


    @VisibleForTesting
    public Uri createVirtualFile(
            String rootId, String path, String mimeType, List<String> streamTypes, byte[] content)
            throws FileNotFoundException, IOException {
        final File file = createFile(rootId, path, mimeType, content);
        final StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
        if (parent == null) {
            throw new FileNotFoundException("Parent not found.");
        }
        final StubDocument document = StubDocument.createVirtualDocument(
                file, mimeType, streamTypes, parent);
        mStorage.put(document.documentId, document);
        return DocumentsContract.buildDocumentUri(mAuthority,  document.documentId);
    }

    @VisibleForTesting
    @VisibleForTesting
    public File getFile(String rootId, String path) throws FileNotFoundException {
    public File getFile(String rootId, String path) throws FileNotFoundException {
        StubDocument root = mRoots.get(rootId).document;
        StubDocument root = mRoots.get(rootId).document;