1 /* 2 * Copyright (C) 2017 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 17 package com.android.documentsui; 18 19 import android.database.Cursor; 20 import android.database.MatrixCursor; 21 import android.database.MergeCursor; 22 import android.provider.DocumentsContract.Document; 23 import android.support.test.filters.SmallTest; 24 import android.test.AndroidTestCase; 25 26 import com.android.documentsui.base.DocumentInfo; 27 import com.android.documentsui.roots.RootCursorWrapper; 28 import com.android.documentsui.testing.TestEventListener; 29 import com.android.documentsui.testing.TestFeatures; 30 31 import java.util.BitSet; 32 import java.util.Random; 33 34 @SmallTest 35 public class ModelTest extends AndroidTestCase { 36 37 private static final int ITEM_COUNT = 10; 38 private static final String AUTHORITY = "test_authority"; 39 40 private static final String[] COLUMNS = new String[]{ 41 RootCursorWrapper.COLUMN_AUTHORITY, 42 Document.COLUMN_DOCUMENT_ID, 43 Document.COLUMN_FLAGS, 44 Document.COLUMN_DISPLAY_NAME, 45 Document.COLUMN_SIZE, 46 Document.COLUMN_LAST_MODIFIED, 47 Document.COLUMN_MIME_TYPE 48 }; 49 50 private static final String[] NAMES = new String[] { 51 "4", 52 "foo", 53 "1", 54 "bar", 55 "*(Ljifl;a", 56 "0", 57 "baz", 58 "2", 59 "3", 60 "%$%VD" 61 }; 62 63 private Cursor cursor; 64 private Model model; 65 private TestFeatures features; 66 67 @Override setUp()68 public void setUp() { 69 features = new TestFeatures(); 70 71 Random rand = new Random(); 72 73 MatrixCursor c = new MatrixCursor(COLUMNS); 74 for (int i = 0; i < ITEM_COUNT; ++i) { 75 MatrixCursor.RowBuilder row = c.newRow(); 76 row.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY); 77 row.add(Document.COLUMN_DOCUMENT_ID, Integer.toString(i)); 78 row.add(Document.COLUMN_FLAGS, Document.FLAG_SUPPORTS_DELETE); 79 // Generate random document names and sizes. This forces the model's internal sort code 80 // to actually do something. 81 row.add(Document.COLUMN_DISPLAY_NAME, NAMES[i]); 82 row.add(Document.COLUMN_SIZE, rand.nextInt()); 83 } 84 cursor = c; 85 86 DirectoryResult r = new DirectoryResult(); 87 r.cursor = cursor; 88 89 // Instantiate the model with a dummy view adapter and listener that (for now) do nothing. 90 model = new Model(features); 91 // not sure why we add a listener here at all. 92 model.addUpdateListener(new TestEventListener<>()); 93 model.update(r); 94 } 95 96 // Tests that the item count is correct. testItemCount()97 public void testItemCount() { 98 assertEquals(ITEM_COUNT, model.getItemCount()); 99 } 100 101 // Tests multiple authorities with clashing document IDs. testModelIdIsUnique()102 public void testModelIdIsUnique() { 103 MatrixCursor cIn1 = new MatrixCursor(COLUMNS); 104 MatrixCursor cIn2 = new MatrixCursor(COLUMNS); 105 106 // Make two sets of items with the same IDs, under different authorities. 107 final String AUTHORITY0 = "auth0"; 108 final String AUTHORITY1 = "auth1"; 109 110 for (int i = 0; i < ITEM_COUNT; ++i) { 111 MatrixCursor.RowBuilder row0 = cIn1.newRow(); 112 row0.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY0); 113 row0.add(Document.COLUMN_DOCUMENT_ID, Integer.toString(i)); 114 115 MatrixCursor.RowBuilder row1 = cIn2.newRow(); 116 row1.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY1); 117 row1.add(Document.COLUMN_DOCUMENT_ID, Integer.toString(i)); 118 } 119 120 Cursor cIn = new MergeCursor(new Cursor[] { cIn1, cIn2 }); 121 122 // Update the model, then make sure it contains all the expected items. 123 DirectoryResult r = new DirectoryResult(); 124 r.cursor = cIn; 125 model.update(r); 126 127 assertEquals(ITEM_COUNT * 2, model.getItemCount()); 128 BitSet b0 = new BitSet(ITEM_COUNT); 129 BitSet b1 = new BitSet(ITEM_COUNT); 130 131 for (String id: model.getModelIds()) { 132 Cursor cOut = model.getItem(id); 133 String authority = 134 DocumentInfo.getCursorString(cOut, RootCursorWrapper.COLUMN_AUTHORITY); 135 String docId = DocumentInfo.getCursorString(cOut, Document.COLUMN_DOCUMENT_ID); 136 137 switch (authority) { 138 case AUTHORITY0: 139 b0.set(Integer.parseInt(docId)); 140 break; 141 case AUTHORITY1: 142 b1.set(Integer.parseInt(docId)); 143 break; 144 default: 145 fail("Unrecognized authority string"); 146 } 147 } 148 149 assertEquals(ITEM_COUNT, b0.cardinality()); 150 assertEquals(ITEM_COUNT, b1.cardinality()); 151 } 152 153 // Tests the base case for Model.getItem. testGetItem()154 public void testGetItem() { 155 String[] ids = model.getModelIds(); 156 assertEquals(ITEM_COUNT, ids.length); 157 for (int i = 0; i < ITEM_COUNT; ++i) { 158 Cursor c = model.getItem(ids[i]); 159 assertEquals(i, c.getPosition()); 160 } 161 } 162 } 163