MtpDatabaseTest.java revision 39795da4c948536c4a9d9ceadece5b03fd395d89
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mtp;
18
19import android.database.Cursor;
20import android.mtp.MtpConstants;
21import android.mtp.MtpObjectInfo;
22import android.provider.DocumentsContract;
23import android.provider.DocumentsContract.Document;
24import android.provider.DocumentsContract.Root;
25import android.test.AndroidTestCase;
26import android.test.suitebuilder.annotation.SmallTest;
27
28import java.io.FileNotFoundException;
29
30import static com.android.mtp.MtpDatabase.strings;
31
32@SmallTest
33public class MtpDatabaseTest extends AndroidTestCase {
34    private final String[] COLUMN_NAMES = new String[] {
35        DocumentsContract.Document.COLUMN_DOCUMENT_ID,
36        MtpDatabaseConstants.COLUMN_DEVICE_ID,
37        MtpDatabaseConstants.COLUMN_STORAGE_ID,
38        MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
39        DocumentsContract.Document.COLUMN_MIME_TYPE,
40        DocumentsContract.Document.COLUMN_DISPLAY_NAME,
41        DocumentsContract.Document.COLUMN_SUMMARY,
42        DocumentsContract.Document.COLUMN_LAST_MODIFIED,
43        DocumentsContract.Document.COLUMN_ICON,
44        DocumentsContract.Document.COLUMN_FLAGS,
45        DocumentsContract.Document.COLUMN_SIZE
46    };
47
48    private final TestResources resources = new TestResources();
49    MtpDatabase mDatabase;
50
51    @Override
52    public void setUp() {
53        mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
54    }
55
56    @Override
57    public void tearDown() {
58        mDatabase.close();
59        mDatabase = null;
60    }
61
62    public void testPutRootDocuments() throws Exception {
63        mDatabase.getMapper().startAddingRootDocuments(0);
64        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
65                new MtpRoot(0, 1, "Device", "Storage", 1000, 2000, ""),
66                new MtpRoot(0, 2, "Device", "Storage", 2000, 4000, ""),
67                new MtpRoot(0, 3, "Device", "/@#%&<>Storage", 3000, 6000,"")
68        });
69
70        {
71            final Cursor cursor = mDatabase.queryRootDocuments(COLUMN_NAMES);
72            assertEquals(3, cursor.getCount());
73
74            cursor.moveToNext();
75            assertEquals("documentId", 1, cursor.getInt(0));
76            assertEquals("deviceId", 0, cursor.getInt(1));
77            assertEquals("storageId", 1, cursor.getInt(2));
78            assertTrue("objectHandle", cursor.isNull(3));
79            assertEquals("mimeType", DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(4));
80            assertEquals("displayName", "Device Storage", cursor.getString(5));
81            assertTrue("summary", cursor.isNull(6));
82            assertTrue("lastModified", cursor.isNull(7));
83            assertEquals("icon", R.drawable.ic_root_mtp, cursor.getInt(8));
84            assertEquals("flag", 0, cursor.getInt(9));
85            assertEquals("size", 1000, cursor.getInt(10));
86
87            cursor.moveToNext();
88            assertEquals("documentId", 2, cursor.getInt(0));
89            assertEquals("displayName", "Device Storage", cursor.getString(5));
90
91            cursor.moveToNext();
92            assertEquals("documentId", 3, cursor.getInt(0));
93            assertEquals("displayName", "Device /@#%&<>Storage", cursor.getString(5));
94
95            cursor.close();
96        }
97
98        {
99            final Cursor cursor = mDatabase.queryRoots(new String [] {
100                    Root.COLUMN_ROOT_ID,
101                    Root.COLUMN_FLAGS,
102                    Root.COLUMN_ICON,
103                    Root.COLUMN_TITLE,
104                    Root.COLUMN_SUMMARY,
105                    Root.COLUMN_DOCUMENT_ID,
106                    Root.COLUMN_AVAILABLE_BYTES,
107                    Root.COLUMN_CAPACITY_BYTES
108            });
109            assertEquals(3, cursor.getCount());
110
111            cursor.moveToNext();
112            assertEquals(1, cursor.getInt(0));
113            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
114            assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
115            assertEquals("Device Storage", cursor.getString(3));
116            assertTrue(cursor.isNull(4));
117            assertEquals(1, cursor.getInt(5));
118            assertEquals(1000, cursor.getInt(6));
119            assertEquals(2000, cursor.getInt(7));
120
121            cursor.moveToNext();
122            assertEquals(2, cursor.getInt(0));
123            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
124            assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
125            assertEquals("Device Storage", cursor.getString(3));
126            assertTrue(cursor.isNull(4));
127            assertEquals(2, cursor.getInt(5));
128            assertEquals(2000, cursor.getInt(6));
129            assertEquals(4000, cursor.getInt(7));
130
131            cursor.moveToNext();
132            assertEquals(3, cursor.getInt(0));
133            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
134            assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
135            assertEquals("Device /@#%&<>Storage", cursor.getString(3));
136            assertTrue(cursor.isNull(4));
137            assertEquals(3, cursor.getInt(5));
138            assertEquals(3000, cursor.getInt(6));
139            assertEquals(6000, cursor.getInt(7));
140
141            cursor.close();
142        }
143    }
144
145    private MtpObjectInfo createDocument(int objectHandle, String name, int format, int size) {
146        final MtpObjectInfo.Builder builder = new MtpObjectInfo.Builder();
147        builder.setObjectHandle(objectHandle);
148        builder.setName(name);
149        builder.setFormat(format);
150        builder.setCompressedSize(size);
151        return builder.build();
152    }
153
154    public void testPutChildDocuments() throws Exception {
155        mDatabase.getMapper().startAddingChildDocuments("parentId");
156        mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
157                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
158                createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
159                createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
160        });
161
162        final Cursor cursor = mDatabase.queryChildDocuments(COLUMN_NAMES, "parentId");
163        assertEquals(3, cursor.getCount());
164
165        cursor.moveToNext();
166        assertEquals("documentId", 1, cursor.getInt(0));
167        assertEquals("deviceId", 0, cursor.getInt(1));
168        assertEquals("storageId", 0, cursor.getInt(2));
169        assertEquals("objectHandle", 100, cursor.getInt(3));
170        assertEquals("mimeType", "text/plain", cursor.getString(4));
171        assertEquals("displayName", "note.txt", cursor.getString(5));
172        assertTrue("summary", cursor.isNull(6));
173        assertTrue("lastModified", cursor.isNull(7));
174        assertTrue("icon", cursor.isNull(8));
175        assertEquals(
176                "flag",
177                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
178                DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
179                cursor.getInt(9));
180        assertEquals("size", 1024, cursor.getInt(10));
181
182        cursor.moveToNext();
183        assertEquals("documentId", 2, cursor.getInt(0));
184        assertEquals("deviceId", 0, cursor.getInt(1));
185        assertEquals("storageId", 0, cursor.getInt(2));
186        assertEquals("objectHandle", 101, cursor.getInt(3));
187        assertEquals("mimeType", "image/jpeg", cursor.getString(4));
188        assertEquals("displayName", "image.jpg", cursor.getString(5));
189        assertTrue("summary", cursor.isNull(6));
190        assertTrue("lastModified", cursor.isNull(7));
191        assertTrue("icon", cursor.isNull(8));
192        assertEquals(
193                "flag",
194                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
195                DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
196                cursor.getInt(9));
197        assertEquals("size", 2 * 1024 * 1024, cursor.getInt(10));
198
199        cursor.moveToNext();
200        assertEquals("documentId", 3, cursor.getInt(0));
201        assertEquals("deviceId", 0, cursor.getInt(1));
202        assertEquals("storageId", 0, cursor.getInt(2));
203        assertEquals("objectHandle", 102, cursor.getInt(3));
204        assertEquals("mimeType", "audio/mpeg", cursor.getString(4));
205        assertEquals("displayName", "music.mp3", cursor.getString(5));
206        assertTrue("summary", cursor.isNull(6));
207        assertTrue("lastModified", cursor.isNull(7));
208        assertTrue("icon", cursor.isNull(8));
209        assertEquals(
210                "flag",
211                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
212                DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
213                cursor.getInt(9));
214        assertEquals("size", 3 * 1024 * 1024, cursor.getInt(10));
215
216        cursor.close();
217    }
218
219    public void testRestoreIdForRootDocuments() throws Exception {
220        final String[] columns = new String[] {
221                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
222                MtpDatabaseConstants.COLUMN_STORAGE_ID,
223                DocumentsContract.Document.COLUMN_DISPLAY_NAME
224        };
225        final String[] rootColumns = new String[] {
226                Root.COLUMN_ROOT_ID,
227                Root.COLUMN_AVAILABLE_BYTES
228        };
229
230        mDatabase.getMapper().startAddingRootDocuments(0);
231        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
232                new MtpRoot(0, 100, "Device", "Storage A", 1000, 0, ""),
233                new MtpRoot(0, 101, "Device", "Storage B", 1001, 0, "")
234        });
235
236        {
237            final Cursor cursor = mDatabase.queryRootDocuments(columns);
238            assertEquals(2, cursor.getCount());
239            cursor.moveToNext();
240            assertEquals("documentId", 1, cursor.getInt(0));
241            assertEquals("storageId", 100, cursor.getInt(1));
242            assertEquals("name", "Device Storage A", cursor.getString(2));
243            cursor.moveToNext();
244            assertEquals("documentId", 2, cursor.getInt(0));
245            assertEquals("storageId", 101, cursor.getInt(1));
246            assertEquals("name", "Device Storage B", cursor.getString(2));
247            cursor.close();
248        }
249
250        {
251            final Cursor cursor = mDatabase.queryRoots(rootColumns);
252            assertEquals(2, cursor.getCount());
253            cursor.moveToNext();
254            assertEquals("rootId", 1, cursor.getInt(0));
255            assertEquals("availableBytes", 1000, cursor.getInt(1));
256            cursor.moveToNext();
257            assertEquals("rootId", 2, cursor.getInt(0));
258            assertEquals("availableBytes", 1001, cursor.getInt(1));
259            cursor.close();
260        }
261
262        mDatabase.getMapper().clearMapping();
263
264        {
265            final Cursor cursor = mDatabase.queryRootDocuments(columns);
266            assertEquals(2, cursor.getCount());
267            cursor.moveToNext();
268            assertEquals("documentId", 1, cursor.getInt(0));
269            assertTrue("storageId", cursor.isNull(1));
270            assertEquals("name", "Device Storage A", cursor.getString(2));
271            cursor.moveToNext();
272            assertEquals("documentId", 2, cursor.getInt(0));
273            assertTrue("storageId", cursor.isNull(1));
274            assertEquals("name", "Device Storage B", cursor.getString(2));
275            cursor.close();
276        }
277
278        {
279            final Cursor cursor = mDatabase.queryRoots(rootColumns);
280            assertEquals(2, cursor.getCount());
281            cursor.moveToNext();
282            assertEquals("rootId", 1, cursor.getInt(0));
283            assertEquals("availableBytes", 1000, cursor.getInt(1));
284            cursor.moveToNext();
285            assertEquals("rootId", 2, cursor.getInt(0));
286            assertEquals("availableBytes", 1001, cursor.getInt(1));
287            cursor.close();
288        }
289
290        mDatabase.getMapper().startAddingRootDocuments(0);
291        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
292                new MtpRoot(0, 200, "Device", "Storage A", 2000, 0, ""),
293                new MtpRoot(0, 202, "Device", "Storage C", 2002, 0, "")
294        });
295
296        {
297            final Cursor cursor = mDatabase.queryRootDocuments(columns);
298            assertEquals(3, cursor.getCount());
299            cursor.moveToNext();
300            assertEquals("documentId", 1, cursor.getInt(0));
301            assertTrue("storageId", cursor.isNull(1));
302            assertEquals("name", "Device Storage A", cursor.getString(2));
303            cursor.moveToNext();
304            assertEquals("documentId", 2, cursor.getInt(0));
305            assertTrue("storageId", cursor.isNull(1));
306            assertEquals("name", "Device Storage B", cursor.getString(2));
307            cursor.moveToNext();
308            assertEquals("documentId", 4, cursor.getInt(0));
309            assertEquals("storageId", 202, cursor.getInt(1));
310            assertEquals("name", "Device Storage C", cursor.getString(2));
311            cursor.close();
312        }
313
314        {
315            final Cursor cursor = mDatabase.queryRoots(rootColumns);
316            assertEquals(3, cursor.getCount());
317            cursor.moveToNext();
318            assertEquals("rootId", 1, cursor.getInt(0));
319            assertEquals("availableBytes", 1000, cursor.getInt(1));
320            cursor.moveToNext();
321            assertEquals("rootId", 2, cursor.getInt(0));
322            assertEquals("availableBytes", 1001, cursor.getInt(1));
323            cursor.moveToNext();
324            assertEquals("rootId", 4, cursor.getInt(0));
325            assertEquals("availableBytes", 2002, cursor.getInt(1));
326            cursor.close();
327        }
328
329        mDatabase.getMapper().stopAddingRootDocuments(0);
330
331        {
332            final Cursor cursor = mDatabase.queryRootDocuments(columns);
333            assertEquals(2, cursor.getCount());
334            cursor.moveToNext();
335            assertEquals("documentId", 1, cursor.getInt(0));
336            assertEquals("storageId", 200, cursor.getInt(1));
337            assertEquals("name", "Device Storage A", cursor.getString(2));
338            cursor.moveToNext();
339            assertEquals("documentId", 4, cursor.getInt(0));
340            assertEquals("storageId", 202, cursor.getInt(1));
341            assertEquals("name", "Device Storage C", cursor.getString(2));
342            cursor.close();
343        }
344
345        {
346            final Cursor cursor = mDatabase.queryRoots(rootColumns);
347            assertEquals(2, cursor.getCount());
348            cursor.moveToNext();
349            assertEquals("rootId", 1, cursor.getInt(0));
350            assertEquals("availableBytes", 2000, cursor.getInt(1));
351            cursor.moveToNext();
352            assertEquals("rootId", 4, cursor.getInt(0));
353            assertEquals("availableBytes", 2002, cursor.getInt(1));
354            cursor.close();
355        }
356    }
357
358    public void testRestoreIdForChildDocuments() throws Exception {
359        final String[] columns = new String[] {
360                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
361                MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
362                DocumentsContract.Document.COLUMN_DISPLAY_NAME
363        };
364        mDatabase.getMapper().startAddingChildDocuments("parentId");
365        mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
366                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
367                createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
368                createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
369        });
370        mDatabase.getMapper().clearMapping();
371
372        {
373            final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId");
374            assertEquals(3, cursor.getCount());
375
376            cursor.moveToNext();
377            assertEquals("documentId", 1, cursor.getInt(0));
378            assertTrue("objectHandle", cursor.isNull(1));
379            assertEquals("name", "note.txt", cursor.getString(2));
380
381            cursor.moveToNext();
382            assertEquals("documentId", 2, cursor.getInt(0));
383            assertTrue("objectHandle", cursor.isNull(1));
384            assertEquals("name", "image.jpg", cursor.getString(2));
385
386            cursor.moveToNext();
387            assertEquals("documentId", 3, cursor.getInt(0));
388            assertTrue("objectHandle", cursor.isNull(1));
389            assertEquals("name", "music.mp3", cursor.getString(2));
390
391            cursor.close();
392        }
393
394        mDatabase.getMapper().startAddingChildDocuments("parentId");
395        mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
396                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
397                createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
398        });
399
400        {
401            final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId");
402            assertEquals(4, cursor.getCount());
403
404            cursor.moveToPosition(3);
405            assertEquals("documentId", 5, cursor.getInt(0));
406            assertEquals("objectHandle", 203, cursor.getInt(1));
407            assertEquals("name", "video.mp4", cursor.getString(2));
408
409            cursor.close();
410        }
411
412        mDatabase.getMapper().stopAddingChildDocuments("parentId");
413
414        {
415            final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId");
416            assertEquals(2, cursor.getCount());
417
418            cursor.moveToNext();
419            assertEquals("documentId", 1, cursor.getInt(0));
420            assertEquals("objectHandle", 200, cursor.getInt(1));
421            assertEquals("name", "note.txt", cursor.getString(2));
422
423            cursor.moveToNext();
424            assertEquals("documentId", 5, cursor.getInt(0));
425            assertEquals("objectHandle", 203, cursor.getInt(1));
426            assertEquals("name", "video.mp4", cursor.getString(2));
427            cursor.close();
428        }
429    }
430
431    public void testRestoreIdForDifferentDevices() throws Exception {
432        final String[] columns = new String[] {
433                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
434                MtpDatabaseConstants.COLUMN_STORAGE_ID,
435                DocumentsContract.Document.COLUMN_DISPLAY_NAME
436        };
437        final String[] rootColumns = new String[] {
438                Root.COLUMN_ROOT_ID,
439                Root.COLUMN_AVAILABLE_BYTES
440        };
441        mDatabase.getMapper().startAddingRootDocuments(0);
442        mDatabase.getMapper().startAddingRootDocuments(1);
443        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
444                new MtpRoot(0, 100, "Device", "Storage", 0, 0, "")
445        });
446        mDatabase.getMapper().putRootDocuments(1, resources, new MtpRoot[] {
447                new MtpRoot(1, 100, "Device", "Storage", 0, 0, "")
448        });
449
450        {
451            final Cursor cursor = mDatabase.queryRootDocuments(columns);
452            assertEquals(2, cursor.getCount());
453            cursor.moveToNext();
454            assertEquals("documentId", 1, cursor.getInt(0));
455            assertEquals("storageId", 100, cursor.getInt(1));
456            assertEquals("name", "Device Storage", cursor.getString(2));
457            cursor.moveToNext();
458            assertEquals("documentId", 2, cursor.getInt(0));
459            assertEquals("storageId", 100, cursor.getInt(1));
460            assertEquals("name", "Device Storage", cursor.getString(2));
461            cursor.close();
462        }
463
464        {
465            final Cursor cursor = mDatabase.queryRoots(rootColumns);
466            assertEquals(2, cursor.getCount());
467            cursor.moveToNext();
468            assertEquals("rootId", 1, cursor.getInt(0));
469            assertEquals("availableBytes", 0, cursor.getInt(1));
470            cursor.moveToNext();
471            assertEquals("rootId", 2, cursor.getInt(0));
472            assertEquals("availableBytes", 0, cursor.getInt(1));
473            cursor.close();
474        }
475
476        mDatabase.getMapper().clearMapping();
477
478        mDatabase.getMapper().startAddingRootDocuments(0);
479        mDatabase.getMapper().startAddingRootDocuments(1);
480        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
481                new MtpRoot(0, 200, "Device", "Storage", 2000, 0, "")
482        });
483        mDatabase.getMapper().putRootDocuments(1, resources, new MtpRoot[] {
484                new MtpRoot(1, 300, "Device", "Storage", 3000, 0, "")
485        });
486        mDatabase.getMapper().stopAddingRootDocuments(0);
487        mDatabase.getMapper().stopAddingRootDocuments(1);
488
489        {
490            final Cursor cursor = mDatabase.queryRootDocuments(columns);
491            assertEquals(2, cursor.getCount());
492            cursor.moveToNext();
493            assertEquals("documentId", 1, cursor.getInt(0));
494            assertEquals("storageId", 200, cursor.getInt(1));
495            assertEquals("name", "Device Storage", cursor.getString(2));
496            cursor.moveToNext();
497            assertEquals("documentId", 2, cursor.getInt(0));
498            assertEquals("storageId", 300, cursor.getInt(1));
499            assertEquals("name", "Device Storage", cursor.getString(2));
500            cursor.close();
501        }
502
503        {
504            final Cursor cursor = mDatabase.queryRoots(rootColumns);
505            assertEquals(2, cursor.getCount());
506            cursor.moveToNext();
507            assertEquals("rootId", 1, cursor.getInt(0));
508            assertEquals("availableBytes", 2000, cursor.getInt(1));
509            cursor.moveToNext();
510            assertEquals("rootId", 2, cursor.getInt(0));
511            assertEquals("availableBytes", 3000, cursor.getInt(1));
512            cursor.close();
513        }
514    }
515
516    public void testRestoreIdForDifferentParents() throws Exception {
517        final String[] columns = new String[] {
518                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
519                MtpDatabaseConstants.COLUMN_OBJECT_HANDLE
520        };
521
522        mDatabase.getMapper().startAddingChildDocuments("parentId1");
523        mDatabase.getMapper().startAddingChildDocuments("parentId2");
524        mDatabase.getMapper().putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
525                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
526        });
527        mDatabase.getMapper().putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
528                createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
529        });
530        mDatabase.getMapper().clearMapping();
531
532        mDatabase.getMapper().startAddingChildDocuments("parentId1");
533        mDatabase.getMapper().startAddingChildDocuments("parentId2");
534        mDatabase.getMapper().putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
535                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
536        });
537        mDatabase.getMapper().putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
538                createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
539        });
540        mDatabase.getMapper().stopAddingChildDocuments("parentId1");
541
542        {
543            final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId1");
544            assertEquals(1, cursor.getCount());
545            cursor.moveToNext();
546            assertEquals("documentId", 1, cursor.getInt(0));
547            assertEquals("objectHandle", 200, cursor.getInt(1));
548            cursor.close();
549        }
550        {
551            final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId2");
552            assertEquals(1, cursor.getCount());
553            cursor.moveToNext();
554            assertEquals("documentId", 2, cursor.getInt(0));
555            assertTrue("objectHandle", cursor.isNull(1));
556            cursor.close();
557        }
558    }
559
560    public void testClearMtpIdentifierBeforeResolveRootDocuments() {
561        final String[] columns = new String[] {
562                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
563                MtpDatabaseConstants.COLUMN_STORAGE_ID,
564                DocumentsContract.Document.COLUMN_DISPLAY_NAME
565        };
566        final String[] rootColumns = new String[] {
567                Root.COLUMN_ROOT_ID,
568                Root.COLUMN_AVAILABLE_BYTES
569        };
570
571        mDatabase.getMapper().startAddingRootDocuments(0);
572        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
573                new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
574        });
575        mDatabase.getMapper().clearMapping();
576
577        mDatabase.getMapper().startAddingRootDocuments(0);
578        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
579                new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
580        });
581        mDatabase.getMapper().clearMapping();
582
583        mDatabase.getMapper().startAddingRootDocuments(0);
584        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
585                new MtpRoot(0, 300, "Device", "Storage", 3000, 0, ""),
586        });
587        mDatabase.getMapper().stopAddingRootDocuments(0);
588
589        {
590            final Cursor cursor = mDatabase.queryRootDocuments(columns);
591            assertEquals(1, cursor.getCount());
592            cursor.moveToNext();
593            assertEquals("documentId", 1, cursor.getInt(0));
594            assertEquals("storageId", 300, cursor.getInt(1));
595            assertEquals("name", "Device Storage", cursor.getString(2));
596            cursor.close();
597        }
598        {
599            final Cursor cursor = mDatabase.queryRoots(rootColumns);
600            assertEquals(1, cursor.getCount());
601            cursor.moveToNext();
602            assertEquals("rootId", 1, cursor.getInt(0));
603            assertEquals("availableBytes", 3000, cursor.getInt(1));
604            cursor.close();
605        }
606    }
607
608    public void testPutSameNameRootsAfterClearing() throws Exception {
609        final String[] columns = new String[] {
610                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
611                MtpDatabaseConstants.COLUMN_STORAGE_ID,
612                DocumentsContract.Document.COLUMN_DISPLAY_NAME
613        };
614        final String[] rootColumns = new String[] {
615                Root.COLUMN_ROOT_ID,
616                Root.COLUMN_AVAILABLE_BYTES
617        };
618
619        mDatabase.getMapper().startAddingRootDocuments(0);
620        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
621                new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
622        });
623        mDatabase.getMapper().clearMapping();
624
625        mDatabase.getMapper().startAddingRootDocuments(0);
626        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
627                new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
628                new MtpRoot(0, 201, "Device", "Storage", 2001, 0, ""),
629        });
630        mDatabase.getMapper().stopAddingRootDocuments(0);
631
632        {
633            final Cursor cursor = mDatabase.queryRootDocuments(columns);
634            assertEquals(2, cursor.getCount());
635            cursor.moveToNext();
636            assertEquals("documentId", 2, cursor.getInt(0));
637            assertEquals("storageId", 200, cursor.getInt(1));
638            assertEquals("name", "Device Storage", cursor.getString(2));
639            cursor.moveToNext();
640            assertEquals("documentId", 3, cursor.getInt(0));
641            assertEquals("storageId", 201, cursor.getInt(1));
642            assertEquals("name", "Device Storage", cursor.getString(2));
643            cursor.close();
644        }
645        {
646            final Cursor cursor = mDatabase.queryRoots(rootColumns);
647            assertEquals(2, cursor.getCount());
648            cursor.moveToNext();
649            assertEquals("rootId", 2, cursor.getInt(0));
650            assertEquals("availableBytes", 2000, cursor.getInt(1));
651            cursor.moveToNext();
652            assertEquals("rootId", 3, cursor.getInt(0));
653            assertEquals("availableBytes", 2001, cursor.getInt(1));
654            cursor.close();
655        }
656    }
657
658    public void testReplaceExistingRoots() {
659        // The client code should be able to replace existing rows with new information.
660        // Add one.
661        mDatabase.getMapper().startAddingRootDocuments(0);
662        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
663                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
664        });
665        mDatabase.getMapper().stopAddingRootDocuments(0);
666        // Replace it.
667        mDatabase.getMapper().startAddingRootDocuments(0);
668        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
669                new MtpRoot(0, 100, "Device", "Storage B", 1000, 1000, ""),
670        });
671        mDatabase.getMapper().stopAddingRootDocuments(0);
672        {
673            final String[] columns = new String[] {
674                    DocumentsContract.Document.COLUMN_DOCUMENT_ID,
675                    MtpDatabaseConstants.COLUMN_STORAGE_ID,
676                    DocumentsContract.Document.COLUMN_DISPLAY_NAME
677            };
678            final Cursor cursor = mDatabase.queryRootDocuments(columns);
679            assertEquals(1, cursor.getCount());
680            cursor.moveToNext();
681            assertEquals("documentId", 1, cursor.getInt(0));
682            assertEquals("storageId", 100, cursor.getInt(1));
683            assertEquals("name", "Device Storage B", cursor.getString(2));
684            cursor.close();
685        }
686        {
687            final String[] columns = new String[] {
688                    Root.COLUMN_ROOT_ID,
689                    Root.COLUMN_AVAILABLE_BYTES
690            };
691            final Cursor cursor = mDatabase.queryRoots(columns);
692            assertEquals(1, cursor.getCount());
693            cursor.moveToNext();
694            assertEquals("rootId", 1, cursor.getInt(0));
695            assertEquals("availableBytes", 1000, cursor.getInt(1));
696            cursor.close();
697        }
698    }
699
700    public void testFailToReplaceExisitingUnmappedRoots() {
701        // The client code should not be able to replace rows before resolving 'unmapped' rows.
702        // Add one.
703        mDatabase.getMapper().startAddingRootDocuments(0);
704        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
705                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
706        });
707        mDatabase.getMapper().clearMapping();
708        final Cursor oldCursor = mDatabase.queryRoots(strings(Root.COLUMN_ROOT_ID));
709        assertEquals(1, oldCursor.getCount());
710
711        // Add one.
712        mDatabase.getMapper().startAddingRootDocuments(0);
713        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
714                new MtpRoot(0, 101, "Device", "Storage B", 1000, 1000, ""),
715        });
716        // Add one more before resolving unmapped documents.
717        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
718                new MtpRoot(0, 102, "Device", "Storage B", 1000, 1000, ""),
719        });
720        mDatabase.getMapper().stopAddingRootDocuments(0);
721
722        // Because the roots shares the same name, the roots should have new IDs.
723        final Cursor newCursor = mDatabase.queryRoots(strings(Root.COLUMN_ROOT_ID));
724        assertEquals(2, newCursor.getCount());
725        oldCursor.moveToNext();
726        newCursor.moveToNext();
727        assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
728        newCursor.moveToNext();
729        assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
730
731        oldCursor.close();
732        newCursor.close();
733    }
734
735    public void testQueryDocument() {
736        mDatabase.getMapper().startAddingRootDocuments(0);
737        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
738                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
739        });
740        mDatabase.getMapper().stopAddingRootDocuments(0);
741
742        final Cursor cursor = mDatabase.queryDocument("1", strings(Document.COLUMN_DISPLAY_NAME));
743        assertEquals(1, cursor.getCount());
744        cursor.moveToNext();
745        assertEquals("Device Storage A", cursor.getString(0));
746        cursor.close();
747    }
748
749    public void testGetParentId() throws FileNotFoundException {
750        mDatabase.getMapper().startAddingRootDocuments(0);
751        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
752                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
753        });
754        mDatabase.getMapper().stopAddingRootDocuments(0);
755
756        mDatabase.getMapper().startAddingChildDocuments("1");
757        mDatabase.getMapper().putChildDocuments(
758                0,
759                "1",
760                new MtpObjectInfo[] {
761                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
762                });
763        mDatabase.getMapper().stopAddingChildDocuments("1");
764
765        assertEquals("1", mDatabase.getParentId("2"));
766    }
767
768    public void testDeleteDocument() {
769        mDatabase.getMapper().startAddingRootDocuments(0);
770        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
771                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
772        });
773        mDatabase.getMapper().stopAddingRootDocuments(0);
774
775        mDatabase.getMapper().startAddingChildDocuments("1");
776        mDatabase.getMapper().putChildDocuments(
777                0,
778                "1",
779                new MtpObjectInfo[] {
780                        createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
781                });
782        mDatabase.getMapper().stopAddingChildDocuments("1");
783
784        mDatabase.getMapper().startAddingChildDocuments("2");
785        mDatabase.getMapper().putChildDocuments(
786                0,
787                "2",
788                new MtpObjectInfo[] {
789                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
790                });
791        mDatabase.getMapper().stopAddingChildDocuments("2");
792
793        mDatabase.deleteDocument("2");
794
795        {
796            // Do not query deleted documents.
797            final Cursor cursor =
798                    mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "1");
799            assertEquals(0, cursor.getCount());
800            cursor.close();
801        }
802
803        {
804            // Child document should be deleted also.
805            final Cursor cursor =
806                    mDatabase.queryDocument("3", strings(Document.COLUMN_DOCUMENT_ID));
807            assertEquals(0, cursor.getCount());
808            cursor.close();
809        }
810    }
811
812    public void testPutNewDocument() {
813        mDatabase.getMapper().startAddingRootDocuments(0);
814        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
815                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
816        });
817        mDatabase.getMapper().stopAddingRootDocuments(0);
818
819        assertEquals(
820                "2",
821                mDatabase.putNewDocument(
822                        0, "1", createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024)));
823
824        {
825            final Cursor cursor =
826                    mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "1");
827            assertEquals(1, cursor.getCount());
828            cursor.moveToNext();
829            assertEquals("2", cursor.getString(0));
830            cursor.close();
831        }
832
833        // The new document should not be mapped with existing invalidated document.
834        mDatabase.getMapper().clearMapping();
835        mDatabase.getMapper().startAddingChildDocuments("1");
836        mDatabase.putNewDocument(
837                0,
838                "1",
839                createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024));
840        mDatabase.getMapper().stopAddingChildDocuments("1");
841
842        {
843            final Cursor cursor =
844                    mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "1");
845            assertEquals(1, cursor.getCount());
846            cursor.moveToNext();
847            assertEquals("3", cursor.getString(0));
848            cursor.close();
849        }
850    }
851}
852