blob: 49878db647fa264589763daf1f2d1fb6fd7bbf5e [file] [log] [blame]
/*
* 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.archives;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract.Document;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import com.android.documentsui.tests.R;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class ReadableArchiveTest {
private static final Uri ARCHIVE_URI = Uri.parse("content://i/love/strawberries");
private static final String NOTIFICATION_URI =
"content://com.android.documentsui.archives/notification-uri";
private ExecutorService mExecutor = null;
private Archive mArchive = null;
private TestUtils mTestUtils = null;
@Before
public void setUp() throws Exception {
mExecutor = Executors.newSingleThreadExecutor();
mTestUtils = new TestUtils(InstrumentationRegistry.getTargetContext(),
InstrumentationRegistry.getContext(), mExecutor);
}
@After
public void tearDown() throws Exception {
mExecutor.shutdown();
assertTrue(mExecutor.awaitTermination(3 /* timeout */, TimeUnit.SECONDS));
if (mArchive != null) {
mArchive.close();
}
}
public static ArchiveId createArchiveId(String path) {
return new ArchiveId(ARCHIVE_URI, ParcelFileDescriptor.MODE_READ_ONLY, path);
}
private void loadArchive(ParcelFileDescriptor descriptor) throws IOException {
mArchive = ReadableArchive.createForParcelFileDescriptor(
InstrumentationRegistry.getTargetContext(),
descriptor,
ARCHIVE_URI,
ParcelFileDescriptor.MODE_READ_ONLY,
Uri.parse(NOTIFICATION_URI));
}
private static void assertRowExist(Cursor cursor, String targetDocId) {
assertTrue(cursor.moveToFirst());
boolean found = false;
final int count = cursor.getCount();
for (int i = 0; i < count; i++) {
cursor.moveToPosition(i);
if (TextUtils.equals(targetDocId, cursor.getString(
cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)))) {
found = true;
break;
}
}
assertTrue(targetDocId + " should be exists", found);
}
@Test
public void testQueryChildDocument() throws IOException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
final Cursor cursor = mArchive.queryChildDocuments(
createArchiveId("/").toDocumentId(), null, null);
assertRowExist(cursor, createArchiveId("/file1.txt").toDocumentId());
assertEquals("file1.txt",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
assertEquals("text/plain",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
assertEquals(13,
cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
assertRowExist(cursor, createArchiveId("/dir1/").toDocumentId());
assertEquals("dir1",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
assertEquals(Document.MIME_TYPE_DIR,
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
assertEquals(0,
cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
assertRowExist(cursor, createArchiveId("/dir2/").toDocumentId());
assertEquals("dir2",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
assertEquals(Document.MIME_TYPE_DIR,
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
assertEquals(0,
cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
// Check if querying children works too.
final Cursor childCursor = mArchive.queryChildDocuments(
createArchiveId("/dir1/").toDocumentId(), null, null);
assertTrue(childCursor.moveToFirst());
assertEquals(
createArchiveId("/dir1/cherries.txt").toDocumentId(),
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DOCUMENT_ID)));
assertEquals("cherries.txt",
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DISPLAY_NAME)));
assertEquals("text/plain",
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_MIME_TYPE)));
assertEquals(17,
childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
}
@Test
public void testQueryChildDocument_NoDirs() throws IOException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.no_dirs));
final Cursor cursor = mArchive.queryChildDocuments(
createArchiveId("/").toDocumentId(), null, null);
assertTrue(cursor.moveToFirst());
assertEquals(
createArchiveId("/dir1/").toDocumentId(),
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
assertEquals("dir1",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
assertEquals(Document.MIME_TYPE_DIR,
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
assertEquals(0,
cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
assertFalse(cursor.moveToNext());
final Cursor childCursor = mArchive.queryChildDocuments(
createArchiveId("/dir1/").toDocumentId(), null, null);
assertTrue(childCursor.moveToFirst());
assertEquals(
createArchiveId("/dir1/dir2/").toDocumentId(),
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DOCUMENT_ID)));
assertEquals("dir2",
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DISPLAY_NAME)));
assertEquals(Document.MIME_TYPE_DIR,
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_MIME_TYPE)));
assertEquals(0,
childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
assertFalse(childCursor.moveToNext());
final Cursor childCursor2 = mArchive.queryChildDocuments(
createArchiveId("/dir1/dir2/").toDocumentId(),
null, null);
assertTrue(childCursor2.moveToFirst());
assertEquals(
createArchiveId("/dir1/dir2/cherries.txt").toDocumentId(),
childCursor2.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DOCUMENT_ID)));
assertFalse(childCursor2.moveToNext());
}
@Test
public void testQueryChildDocument_EmptyDirs() throws IOException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.empty_dirs));
final Cursor cursor = mArchive.queryChildDocuments(
createArchiveId("/").toDocumentId(), null, null);
assertTrue(cursor.moveToFirst());
assertEquals(
createArchiveId("/dir1/").toDocumentId(),
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
assertEquals("dir1",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
assertEquals(Document.MIME_TYPE_DIR,
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
assertEquals(0,
cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
assertFalse(cursor.moveToNext());
final Cursor childCursor = mArchive.queryChildDocuments(
createArchiveId("/dir1/").toDocumentId(), null, null);
assertRowExist(childCursor, createArchiveId("/dir1/dir2/").toDocumentId());
assertEquals("dir2",
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DISPLAY_NAME)));
assertEquals(Document.MIME_TYPE_DIR,
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_MIME_TYPE)));
assertEquals(0,
childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
assertRowExist(childCursor, createArchiveId("/dir1/dir3/").toDocumentId());
assertEquals(
createArchiveId("/dir1/dir3/").toDocumentId(),
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DOCUMENT_ID)));
assertEquals("dir3",
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_DISPLAY_NAME)));
assertEquals(Document.MIME_TYPE_DIR,
childCursor.getString(childCursor.getColumnIndexOrThrow(
Document.COLUMN_MIME_TYPE)));
assertEquals(0,
childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
final Cursor childCursor2 = mArchive.queryChildDocuments(
createArchiveId("/dir1/dir2/").toDocumentId(),
null, null);
assertFalse(childCursor2.moveToFirst());
final Cursor childCursor3 = mArchive.queryChildDocuments(
createArchiveId("/dir1/dir3/").toDocumentId(),
null, null);
assertFalse(childCursor3.moveToFirst());
}
@Test
public void testGetDocumentType() throws IOException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
assertEquals(Document.MIME_TYPE_DIR, mArchive.getDocumentType(
createArchiveId("/dir1/").toDocumentId()));
assertEquals("text/plain", mArchive.getDocumentType(
createArchiveId("/file1.txt").toDocumentId()));
}
@Test
public void testIsChildDocument() throws IOException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
final String documentId = createArchiveId("/").toDocumentId();
assertTrue(mArchive.isChildDocument(documentId,
createArchiveId("/dir1/").toDocumentId()));
assertFalse(mArchive.isChildDocument(documentId,
createArchiveId("/this-does-not-exist").toDocumentId()));
assertTrue(mArchive.isChildDocument(
createArchiveId("/dir1/").toDocumentId(),
createArchiveId("/dir1/cherries.txt").toDocumentId()));
assertTrue(mArchive.isChildDocument(documentId,
createArchiveId("/dir1/cherries.txt").toDocumentId()));
}
@Test
public void testQueryDocument() throws IOException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
final Cursor cursor = mArchive.queryDocument(
createArchiveId("/dir2/strawberries.txt").toDocumentId(),
null);
assertTrue(cursor.moveToFirst());
assertEquals(
createArchiveId("/dir2/strawberries.txt").toDocumentId(),
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
assertEquals("strawberries.txt",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
assertEquals("text/plain",
cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
assertEquals(21,
cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
}
@Test
public void testOpenDocument() throws IOException, ErrnoException {
loadArchive(mTestUtils.getSeekableDescriptor(R.raw.archive));
commonTestOpenDocument();
}
@Test
public void testOpenDocument_NonSeekable() throws IOException, ErrnoException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
commonTestOpenDocument();
}
// Common part of testOpenDocument and testOpenDocument_NonSeekable.
void commonTestOpenDocument() throws IOException, ErrnoException {
final ParcelFileDescriptor descriptor = mArchive.openDocument(
createArchiveId("/dir2/strawberries.txt").toDocumentId(),
"r", null /* signal */);
assertTrue(Archive.canSeek(descriptor));
try (final ParcelFileDescriptor.AutoCloseInputStream inputStream =
new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) {
Os.lseek(descriptor.getFileDescriptor(), "I love ".length(), OsConstants.SEEK_SET);
assertEquals("strawberries!", new Scanner(inputStream).nextLine());
Os.lseek(descriptor.getFileDescriptor(), 0, OsConstants.SEEK_SET);
assertEquals("I love strawberries!", new Scanner(inputStream).nextLine());
}
}
@Test
public void testCanSeek() throws IOException {
assertTrue(Archive.canSeek(mTestUtils.getSeekableDescriptor(R.raw.archive)));
assertFalse(Archive.canSeek(mTestUtils.getNonSeekableDescriptor(R.raw.archive)));
}
@Test
public void testBrokenArchive() throws IOException {
loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
final Cursor cursor = mArchive.queryChildDocuments(
createArchiveId("/").toDocumentId(), null, null);
}
}