/*
 * 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.mtp;

import android.database.Cursor;
import android.media.MediaFile;
import android.media.MediaFile.MediaFileType;
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import java.io.FileNotFoundException;
import java.util.Arrays;

import static android.provider.DocumentsContract.Document.*;
import static com.android.mtp.MtpDatabase.strings;
import static com.android.mtp.MtpDatabaseConstants.*;
import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;

@SmallTest
public class MtpDatabaseTest extends AndroidTestCase {
    private static final String[] COLUMN_NAMES = new String[] {
        DocumentsContract.Document.COLUMN_DOCUMENT_ID,
        MtpDatabaseConstants.COLUMN_DEVICE_ID,
        MtpDatabaseConstants.COLUMN_STORAGE_ID,
        MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
        DocumentsContract.Document.COLUMN_MIME_TYPE,
        DocumentsContract.Document.COLUMN_DISPLAY_NAME,
        DocumentsContract.Document.COLUMN_SUMMARY,
        DocumentsContract.Document.COLUMN_LAST_MODIFIED,
        DocumentsContract.Document.COLUMN_ICON,
        DocumentsContract.Document.COLUMN_FLAGS,
        DocumentsContract.Document.COLUMN_SIZE,
        MtpDatabaseConstants.COLUMN_DOCUMENT_TYPE
    };

    private final TestResources resources = new TestResources();
    MtpDatabase mDatabase;

    @Override
    public void setUp() {
        mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
    }

    @Override
    public void tearDown() {
        mDatabase.close();
        mDatabase = null;
    }

    private static int getInt(Cursor cursor, String columnName) {
        return cursor.getInt(cursor.getColumnIndex(columnName));
    }

    private static boolean isNull(Cursor cursor, String columnName) {
        return cursor.isNull(cursor.getColumnIndex(columnName));
    }

    private static String getString(Cursor cursor, String columnName) {
        return cursor.getString(cursor.getColumnIndex(columnName));
    }

    public void testPutSingleStorageDocuments() throws Exception {
        addTestDevice();

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 1, "Storage", 1000, 2000, "")
        });
        mDatabase.getMapper().stopAddingDocuments("1");

        {
            final Cursor cursor = mDatabase.queryRootDocuments(COLUMN_NAMES);
            assertEquals(1, cursor.getCount());

            cursor.moveToNext();
            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
            assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
            assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
            assertEquals(
                    DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
            assertTrue(isNull(cursor, COLUMN_SUMMARY));
            assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
            assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
            assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
            assertEquals(1000, getInt(cursor, COLUMN_SIZE));
            assertEquals(
                    MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE,
                    getInt(cursor, COLUMN_DOCUMENT_TYPE));

            cursor.close();
        }

        {
            final Cursor cursor = mDatabase.queryRoots(resources, new String [] {
                    Root.COLUMN_ROOT_ID,
                    Root.COLUMN_FLAGS,
                    Root.COLUMN_ICON,
                    Root.COLUMN_TITLE,
                    Root.COLUMN_SUMMARY,
                    Root.COLUMN_DOCUMENT_ID,
                    Root.COLUMN_AVAILABLE_BYTES,
                    Root.COLUMN_CAPACITY_BYTES
            });
            assertEquals(1, cursor.getCount());

            cursor.moveToNext();
            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
            assertEquals(
                    Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY,
                    getInt(cursor, Root.COLUMN_FLAGS));
            assertEquals(R.drawable.ic_root_mtp, getInt(cursor, Root.COLUMN_ICON));
            assertEquals("Device Storage", getString(cursor, Root.COLUMN_TITLE));
            assertTrue(isNull(cursor, Root.COLUMN_SUMMARY));
            assertEquals(1, getInt(cursor, Root.COLUMN_DOCUMENT_ID));
            assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
            assertEquals(2000, getInt(cursor, Root.COLUMN_CAPACITY_BYTES));

            cursor.close();
        }
    }

    public void testPutStorageDocuments() throws Exception {
        addTestDevice();

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 1, "Storage", 1000, 2000, ""),
                new MtpRoot(0, 2, "Storage", 2000, 4000, ""),
                new MtpRoot(0, 3, "/@#%&<>Storage", 3000, 6000,"")
        });

        {
            final Cursor cursor = mDatabase.queryRootDocuments(COLUMN_NAMES);
            assertEquals(3, cursor.getCount());

            cursor.moveToNext();
            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
            assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
            assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
            assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
            assertTrue(isNull(cursor, COLUMN_SUMMARY));
            assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
            assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
            assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
            assertEquals(1000, getInt(cursor, COLUMN_SIZE));
            assertEquals(
                    MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE, getInt(cursor, COLUMN_DOCUMENT_TYPE));

            cursor.moveToNext();
            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));

            cursor.moveToNext();
            assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals("/@#%&<>Storage", getString(cursor, COLUMN_DISPLAY_NAME));

            cursor.close();
        }
    }

    private MtpObjectInfo createDocument(int objectHandle, String name, int format, int size) {
        final MtpObjectInfo.Builder builder = new MtpObjectInfo.Builder();
        builder.setObjectHandle(objectHandle);
        builder.setName(name);
        builder.setFormat(format);
        builder.setCompressedSize(size);
        return builder.build();
    }

    public void testPutChildDocuments() throws Exception {
        addTestDevice();
        addTestStorage("1");

        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
                createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
        }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});

        final Cursor cursor = mDatabase.queryChildDocuments(COLUMN_NAMES, "2");
        assertEquals(3, cursor.getCount());

        cursor.moveToNext();
        assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
        assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
        assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
        assertEquals(100, getInt(cursor, COLUMN_OBJECT_HANDLE));
        assertEquals("text/plain", getString(cursor, COLUMN_MIME_TYPE));
        assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
        assertTrue(isNull(cursor, COLUMN_SUMMARY));
        assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
        assertTrue(isNull(cursor, COLUMN_ICON));
        assertEquals(
                COLUMN_FLAGS,
                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
                cursor.getInt(9));
        assertEquals(1024, getInt(cursor, COLUMN_SIZE));
        assertEquals(
                MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));

        cursor.moveToNext();
        assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
        assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
        assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
        assertEquals(101, getInt(cursor, COLUMN_OBJECT_HANDLE));
        assertEquals("image/jpeg", getString(cursor, COLUMN_MIME_TYPE));
        assertEquals("image.jpg", getString(cursor, COLUMN_DISPLAY_NAME));
        assertTrue(isNull(cursor, COLUMN_SUMMARY));
        assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
        assertTrue(isNull(cursor, COLUMN_ICON));
        assertEquals(
                COLUMN_FLAGS,
                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
                DocumentsContract.Document.FLAG_SUPPORTS_METADATA,
                cursor.getInt(9));
        assertEquals(2 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
        assertEquals(
                MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));

        cursor.moveToNext();
        assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
        assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
        assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
        assertEquals(102, getInt(cursor, COLUMN_OBJECT_HANDLE));
        assertEquals("audio/mpeg", getString(cursor, COLUMN_MIME_TYPE));
        assertEquals("music.mp3", getString(cursor, COLUMN_DISPLAY_NAME));
        assertTrue(isNull(cursor, COLUMN_SUMMARY));
        assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
        assertTrue(isNull(cursor, COLUMN_ICON));
        assertEquals(
                COLUMN_FLAGS,
                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
                cursor.getInt(9));
        assertEquals(3 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
        assertEquals(
                MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));

        cursor.close();
    }

    public void testPutChildDocuments_operationsSupported() throws Exception {
        addTestDevice();
        addTestStorage("1");

        // Put a document with empty supported operations.
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", new int[0], new MtpObjectInfo[] {
                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
        }, new long[] { 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        try (final Cursor cursor =
                mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(0, cursor.getInt(0));
        }

        // Put a document with writable operations.
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
                MtpConstants.OPERATION_SEND_OBJECT,
                MtpConstants.OPERATION_SEND_OBJECT_INFO,
        }, new MtpObjectInfo[] {
                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
        }, new long[] { 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        try (final Cursor cursor =
                mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(Document.FLAG_SUPPORTS_WRITE, cursor.getInt(0));
        }

        // Put a document with deletable operations.
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
                MtpConstants.OPERATION_DELETE_OBJECT
        }, new MtpObjectInfo[] {
                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
        }, new long[] { 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        try (final Cursor cursor =
                mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(Document.FLAG_SUPPORTS_DELETE, cursor.getInt(0));
        }
    }

    public void testRestoreIdForRootDocuments() throws Exception {
        final String[] columns = new String[] {
                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                MtpDatabaseConstants.COLUMN_STORAGE_ID,
                DocumentsContract.Document.COLUMN_DISPLAY_NAME
        };

        // Add device and two storages.
        addTestDevice();
        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage A", 1000, 0, ""),
                new MtpRoot(0, 101, "Storage B", 1001, 0, "")
        });

        {
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.moveToNext();
            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(101, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.close();
        }

        // Clear mapping and add a device.
        mDatabase.getMapper().clearMapping();
        addTestDevice();

        {
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(0, cursor.getCount());
            cursor.close();
        }

        // Add two storages, but one's name is different from previous one.
        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 200, "Storage A", 2000, 0, ""),
                new MtpRoot(0, 202, "Storage C", 2002, 0, "")
        });
        mDatabase.getMapper().stopAddingDocuments("1");

        {
            // After compeleting mapping, Storage A can be obtained with new storage ID.
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.moveToNext();
            assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.close();
        }
    }

    public void testRestoreIdForChildDocuments() throws Exception {
        final String[] columns = new String[] {
                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
                DocumentsContract.Document.COLUMN_DISPLAY_NAME
        };

        addTestDevice();
        addTestStorage("1");

        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
                createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
        }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
        mDatabase.getMapper().clearMapping();

        addTestDevice();
        addTestStorage("1");

        {
            // Don't return objects that lost MTP object handles.
            final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
            assertEquals(0, cursor.getCount());
            cursor.close();
        }

        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
        }, new long[] { 1024L, 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        {
            final Cursor cursor = mDatabase.queryChildDocuments(columns, "2");
            assertEquals(2, cursor.getCount());

            cursor.moveToNext();
            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
            assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));

            cursor.moveToNext();
            assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
            assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));

            cursor.close();
        }
    }

    public void testRestoreIdForDifferentDevices() throws Exception {
        final String[] columns = new String[] {
                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                MtpDatabaseConstants.COLUMN_STORAGE_ID,
                DocumentsContract.Document.COLUMN_DISPLAY_NAME
        };
        final String[] rootColumns = new String[] {
                Root.COLUMN_ROOT_ID,
                Root.COLUMN_AVAILABLE_BYTES
        };
        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
        mDatabase.getMapper().stopAddingDocuments(null);

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage", 0, 0, "")
        });
        mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(1, 100, "Storage", 0, 0, "")
        });

        {
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.moveToNext();
            assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.close();
        }

        {
            final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
            assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
            cursor.moveToNext();
            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
            assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
            cursor.close();
        }

        mDatabase.getMapper().clearMapping();

        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device A", "Device key A", true, new MtpRoot[0], null, null));
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                1, "Device B", "Device key B", true, new MtpRoot[0], null, null));
        mDatabase.getMapper().stopAddingDocuments(null);

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 200, "Storage", 2000, 0, "")
        });
        mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(1, 300, "Storage", 3000, 0, "")
        });
        mDatabase.getMapper().stopAddingDocuments("1");
        mDatabase.getMapper().stopAddingDocuments("2");

        {
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.moveToNext();
            assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.close();
        }

        {
            final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
            assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
            cursor.moveToNext();
            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
            assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
            cursor.close();
        }
    }

    public void testRestoreIdForDifferentParents() throws Exception {
        final String[] columns = new String[] {
                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                MtpDatabaseConstants.COLUMN_OBJECT_HANDLE
        };

        // Add device, storage, and two directories.
        addTestDevice();
        addTestStorage("1");
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
                createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
        }, new long[] { 0L, 0L });
        mDatabase.getMapper().stopAddingDocuments("2");

        // Put note.txt in each directory.
        mDatabase.getMapper().startAddingDocuments("3");
        mDatabase.getMapper().startAddingDocuments("4");
        mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L });
        mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L });

        // Clear mapping.
        mDatabase.getMapper().clearMapping();

        // Add device, storage, and two directories again.
        addTestDevice();
        addTestStorage("1");
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
                createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
        }, new long[] { 0L, 0L });
        mDatabase.getMapper().stopAddingDocuments("2");

        // Add note.txt in each directory again.
        mDatabase.getMapper().startAddingDocuments("3");
        mDatabase.getMapper().startAddingDocuments("4");
        mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L });
        mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L });
        mDatabase.getMapper().stopAddingDocuments("3");
        mDatabase.getMapper().stopAddingDocuments("4");

        // Check if the two note.txt are mapped correctly.
        {
            final Cursor cursor = mDatabase.queryChildDocuments(columns, "3");
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
            cursor.close();
        }
        {
            final Cursor cursor = mDatabase.queryChildDocuments(columns, "4");
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(201, getInt(cursor, COLUMN_OBJECT_HANDLE));
            cursor.close();
        }
    }

    public void testClearMtpIdentifierBeforeResolveRootDocuments() throws Exception {
        final String[] columns = new String[] {
                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                MtpDatabaseConstants.COLUMN_STORAGE_ID,
                DocumentsContract.Document.COLUMN_DISPLAY_NAME
        };
        final String[] rootColumns = new String[] {
                Root.COLUMN_ROOT_ID,
                Root.COLUMN_AVAILABLE_BYTES
        };

        addTestDevice();

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage", 0, 0, ""),
        });
        mDatabase.getMapper().clearMapping();

        addTestDevice();

        try (final Cursor cursor = mDatabase.queryRoots(resources, rootColumns)) {
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals("1", getString(cursor, Root.COLUMN_ROOT_ID));
        }

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 200, "Storage", 2000, 0, ""),
        });
        mDatabase.getMapper().clearMapping();

        addTestDevice();

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 300, "Storage", 3000, 0, ""),
        });
        mDatabase.getMapper().stopAddingDocuments("1");

        {
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.close();
        }
        {
            final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
            assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
            cursor.close();
        }
    }

    public void testPutSameNameRootsAfterClearing() throws Exception {
        final String[] columns = new String[] {
                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                MtpDatabaseConstants.COLUMN_STORAGE_ID,
                DocumentsContract.Document.COLUMN_DISPLAY_NAME
        };

        // Add a device and a storage.
        addTestDevice();
        addTestStorage("1");

        // Disconnect devices.
        mDatabase.getMapper().clearMapping();

        // Add a device and two storages that has same name.
        addTestDevice();
        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 200, "Storage", 2000, 0, ""),
                new MtpRoot(0, 201, "Storage", 2001, 0, ""),
        });
        mDatabase.getMapper().stopAddingDocuments("1");

        {
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(2, cursor.getCount());

            // First storage reuse document ID of previous storage.
            cursor.moveToNext();
            // One reuses exisitng document ID 1.
            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));

            // Second one has new document ID.
            cursor.moveToNext();
            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(201, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));

            cursor.close();
        }
    }

    public void testReplaceExistingRoots() throws Exception {
        addTestDevice();

        // The client code should be able to replace existing rows with new information.
        // Add one.
        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
        });
        mDatabase.getMapper().stopAddingDocuments("1");
        // Replace it.
        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage B", 1000, 1000, ""),
        });
        mDatabase.getMapper().stopAddingDocuments("1");
        {
            final String[] columns = new String[] {
                    DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                    MtpDatabaseConstants.COLUMN_STORAGE_ID,
                    DocumentsContract.Document.COLUMN_DISPLAY_NAME
            };
            final Cursor cursor = mDatabase.queryRootDocuments(columns);
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
            assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
            cursor.close();
        }
        {
            final String[] columns = new String[] {
                    Root.COLUMN_ROOT_ID,
                    Root.COLUMN_TITLE,
                    Root.COLUMN_AVAILABLE_BYTES
            };
            final Cursor cursor = mDatabase.queryRoots(resources, columns);
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
            assertEquals("Device Storage B", getString(cursor, Root.COLUMN_TITLE));
            assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
            cursor.close();
        }
    }

    public void testFailToReplaceExisitingUnmappedRoots() throws Exception {
        // The client code should not be able to replace rows before resolving 'unmapped' rows.
        // Add one.
        addTestDevice();
        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
        });
        mDatabase.getMapper().clearMapping();

        addTestDevice();
        try (final Cursor oldCursor =
                mDatabase.queryRoots(resources, strings(Root.COLUMN_ROOT_ID))) {
            assertEquals(1, oldCursor.getCount());
            oldCursor.moveToNext();
            assertEquals("1", getString(oldCursor, Root.COLUMN_ROOT_ID));

            // Add one.
            mDatabase.getMapper().startAddingDocuments("1");
            mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                    new MtpRoot(0, 101, "Storage B", 1000, 1000, ""),
            });
            // Add one more before resolving unmapped documents.
            mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                    new MtpRoot(0, 102, "Storage B", 1000, 1000, ""),
            });
            mDatabase.getMapper().stopAddingDocuments("1");

            // Because the roots shares the same name, the roots should have new IDs.
            try (final Cursor newCursor = mDatabase.queryChildDocuments(
                    strings(Document.COLUMN_DOCUMENT_ID), "1")) {
                assertEquals(2, newCursor.getCount());
                newCursor.moveToNext();
                assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
                newCursor.moveToNext();
                assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
            }
        }
    }

    public void testQueryDocuments() throws Exception {
        addTestDevice();
        addTestStorage("1");

        final Cursor cursor = mDatabase.queryDocument("2", strings(Document.COLUMN_DISPLAY_NAME));
        assertEquals(1, cursor.getCount());
        cursor.moveToNext();
        assertEquals("Storage", getString(cursor, Document.COLUMN_DISPLAY_NAME));
        cursor.close();
    }

    public void testQueryRoots() throws Exception {
        // Add device document.
        addTestDevice();

        // It the device does not have storages, it shows a device root.
        {
            final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals("Device", cursor.getString(0));
            cursor.close();
        }

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage A", 0, 0, "")
        });
        mDatabase.getMapper().stopAddingDocuments("1");

        // It the device has single storage, it shows a storage root.
        {
            final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals("Device Storage A", cursor.getString(0));
            cursor.close();
        }

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
                new MtpRoot(0, 101, "Storage B", 0, 0, "")
        });
        mDatabase.getMapper().stopAddingDocuments("1");

        // It the device has multiple storages, it shows a device root.
        {
            final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals("Device", cursor.getString(0));
            cursor.close();
        }
    }

    public void testGetParentId() throws FileNotFoundException {
        addTestDevice();

        mDatabase.getMapper().startAddingDocuments("1");
        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
        });
        mDatabase.getMapper().stopAddingDocuments("1");

        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        assertEquals("2", mDatabase.getParentIdentifier("3").mDocumentId);
    }

    public void testDeleteDocument() throws Exception {
        addTestDevice();
        addTestStorage("1");

        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
        }, new long[] { 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        mDatabase.getMapper().startAddingDocuments("3");
        mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L });
        mDatabase.getMapper().stopAddingDocuments("3");

        mDatabase.deleteDocument("3");

        {
            // Do not query deleted documents.
            final Cursor cursor =
                    mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
            assertEquals(0, cursor.getCount());
            cursor.close();
        }

        {
            // Child document should be deleted also.
            final Cursor cursor =
                    mDatabase.queryDocument("4", strings(Document.COLUMN_DOCUMENT_ID));
            assertEquals(0, cursor.getCount());
            cursor.close();
        }
    }

    public void testPutNewDocument() throws Exception {
        addTestDevice();
        addTestStorage("1");

        assertEquals(
                "3",
                mDatabase.putNewDocument(
                        0, "2", OPERATIONS_SUPPORTED,
                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                        1024L));

        {
            final Cursor cursor =
                    mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals("3", cursor.getString(0));
            cursor.close();
        }

        // The new document should not be mapped with existing invalidated document.
        mDatabase.getMapper().clearMapping();
        addTestDevice();
        addTestStorage("1");

        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.putNewDocument(
                0, "2", OPERATIONS_SUPPORTED,
                createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                1024L);
        mDatabase.getMapper().stopAddingDocuments("2");

        {
            final Cursor cursor =
                    mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "2");
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals("4", cursor.getString(0));
            cursor.close();
        }
    }

    public void testGetDocumentIdForDevice() throws Exception {
        addTestDevice();
        assertEquals("1", mDatabase.getDocumentIdForDevice(0));
    }

    public void testGetClosedDevice() throws Exception {
        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device", null /* deviceKey */, /* opened is */ false, new MtpRoot[0], null,
                null));
        mDatabase.getMapper().stopAddingDocuments(null);

        final String[] columns = new String [] {
                DocumentsContract.Root.COLUMN_ROOT_ID,
                DocumentsContract.Root.COLUMN_TITLE,
                DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
        };
        try (final Cursor cursor = mDatabase.queryRoots(resources, columns)) {
            assertEquals(1, cursor.getCount());
            assertTrue(cursor.moveToNext());
            assertEquals(1, cursor.getLong(0));
            assertEquals("Device", cursor.getString(1));
            assertTrue(cursor.isNull(2));
        }
    }

    public void testMappingWithoutKey() throws FileNotFoundException {
        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
                null));
        mDatabase.getMapper().stopAddingDocuments(null);

        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
                null));
        mDatabase.getMapper().stopAddingDocuments(null);

        try (final Cursor cursor =
                mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
            assertEquals(1, cursor.getCount());
            assertTrue(cursor.moveToNext());
            assertEquals(1, cursor.getLong(0));
        }
    }

    public void testMappingFailsWithoutKey() throws FileNotFoundException {
        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
                null));
        mDatabase.getMapper().stopAddingDocuments(null);

        // MTP identifier is cleared here. Mapping no longer works without device key.
        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().stopAddingDocuments(null);

        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device", null /* device key */, /* opened is */ true, new MtpRoot[0], null,
                null));
        mDatabase.getMapper().stopAddingDocuments(null);

        try (final Cursor cursor =
                mDatabase.queryRoots(resources, strings(DocumentsContract.Root.COLUMN_ROOT_ID))) {
            assertEquals(1, cursor.getCount());
            assertTrue(cursor.moveToNext());
            assertEquals(2, cursor.getLong(0));
        }
    }

    public void testUpdateDocumentWithoutChange() throws FileNotFoundException {
        mDatabase.getMapper().startAddingDocuments(null);
        assertTrue(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
                null)));
        assertFalse(mDatabase.getMapper().stopAddingDocuments(null));

        mDatabase.getMapper().startAddingDocuments(null);
        assertFalse(mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
                0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
                null)));
        assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
    }

    public void testSetBootCount() {
        assertEquals(0, mDatabase.getLastBootCount());
        mDatabase.setLastBootCount(10);
        assertEquals(10, mDatabase.getLastBootCount());
        try {
            mDatabase.setLastBootCount(-1);
            fail();
        } catch (IllegalArgumentException e) {}
    }

    public void testCleanDatabase() throws FileNotFoundException {
        // Add tree.
        addTestDevice();
        addTestStorage("1");
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
                createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L, 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        // Disconnect the device.
        mDatabase.getMapper().startAddingDocuments(null);
        mDatabase.getMapper().stopAddingDocuments(null);

        // Clean database.
        mDatabase.cleanDatabase(new Uri[] {
                DocumentsContract.buildDocumentUri(MtpDocumentsProvider.AUTHORITY, "3")
        });

        // Add tree again.
        addTestDevice();
        addTestStorage("1");
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
                createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
        }, new long[] { 1024L, 1024L });
        mDatabase.getMapper().stopAddingDocuments("2");

        try (final Cursor cursor = mDatabase.queryChildDocuments(
                strings(COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME), "2")) {
            assertEquals(2, cursor.getCount());

            // Persistent uri uses the same ID.
            cursor.moveToNext();
            assertEquals("3", cursor.getString(0));
            assertEquals("apple.txt", cursor.getString(1));

            // Others does not.
            cursor.moveToNext();
            assertEquals("5", cursor.getString(0));
            assertEquals("orange.txt", cursor.getString(1));
        }
    }

    public void testFormatCodeForMpeg() throws FileNotFoundException {
        addTestDevice();
        addTestStorage("1");
        mDatabase.getMapper().startAddingDocuments("2");
        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
            createDocument(100, "audio.m4a", MtpConstants.FORMAT_MPEG, 1000),
            createDocument(101, "video.m4v", MtpConstants.FORMAT_MPEG, 1000),
            createDocument(102, "unknown.mp4", MtpConstants.FORMAT_MPEG, 1000),
            createDocument(103, "inconsistent.txt", MtpConstants.FORMAT_MPEG, 1000),
            createDocument(104, "noext", MtpConstants.FORMAT_UNDEFINED, 1000),
        }, new long[] { 1000L, 1000L, 1000L, 1000L, 1000L });
        mDatabase.getMapper().stopAddingDocuments("2");
        try (final Cursor cursor = mDatabase.queryChildDocuments(
                strings(COLUMN_DISPLAY_NAME,  COLUMN_MIME_TYPE),
                "2")) {
            assertEquals(5, cursor.getCount());
            cursor.moveToNext();
            assertEquals("audio.m4a", cursor.getString(0));
            assertEquals("audio/mp4", cursor.getString(1));
            cursor.moveToNext();
            assertEquals("video.m4v", cursor.getString(0));
            assertEquals("video/mp4", cursor.getString(1));
            cursor.moveToNext();
            // Assume that the file is video as we don't have any hints to find out if the file is
            // video or audio.
            assertEquals("unknown.mp4", cursor.getString(0));
            assertEquals("video/mp4", cursor.getString(1));
            // Don't return mime type that is inconsistent with format code.
            cursor.moveToNext();
            assertEquals("inconsistent.txt", cursor.getString(0));
            assertEquals("video/mpeg", cursor.getString(1));
            cursor.moveToNext();
            assertEquals("noext", cursor.getString(0));
            assertEquals("application/octet-stream", cursor.getString(1));
        }
    }

    private void addTestDevice() throws FileNotFoundException {
        TestUtil.addTestDevice(mDatabase);
    }

    private void addTestStorage(String parentId) throws FileNotFoundException {
        TestUtil.addTestStorage(mDatabase, parentId);
    }
}
