1 /* 2 * Copyright (C) 2009 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.server; 18 19 import android.content.ContentResolver; 20 import android.content.Context; 21 import android.content.ContextWrapper; 22 import android.content.Intent; 23 import android.os.DropBoxManager; 24 import android.os.Looper; 25 import android.os.Parcel; 26 import android.os.ParcelFileDescriptor; 27 import android.os.Parcelable; 28 import android.os.Process; 29 import android.os.StatFs; 30 import android.os.UserHandle; 31 import android.provider.Settings; 32 import android.test.AndroidTestCase; 33 34 import com.android.server.DropBoxManagerService.EntryFile; 35 36 import java.io.BufferedReader; 37 import java.io.File; 38 import java.io.FileOutputStream; 39 import java.io.FileWriter; 40 import java.io.IOException; 41 import java.io.InputStream; 42 import java.io.InputStreamReader; 43 import java.util.Random; 44 import java.util.zip.GZIPOutputStream; 45 46 /** 47 * Test {@link DropBoxManager} functionality. 48 * 49 * Run with: 50 * bit FrameworksServicesTests:com.android.server.DropBoxTest 51 */ 52 public class DropBoxTest extends AndroidTestCase { 53 private Context mContext; 54 55 @Override setUp()56 protected void setUp() throws Exception { 57 super.setUp(); 58 59 mContext = new ContextWrapper(super.getContext()) { 60 @Override 61 public void sendBroadcastAsUser(Intent intent, 62 UserHandle user, String receiverPermission) { 63 // Don't actually send broadcasts. 64 } 65 }; 66 } 67 tearDown()68 public void tearDown() throws Exception { 69 ContentResolver cr = getContext().getContentResolver(); 70 Settings.Global.putString(cr, Settings.Global.DROPBOX_AGE_SECONDS, ""); 71 Settings.Global.putString(cr, Settings.Global.DROPBOX_MAX_FILES, ""); 72 Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, ""); 73 Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest", ""); 74 } 75 76 @Override getContext()77 public Context getContext() { 78 return mContext; 79 } 80 testAddText()81 public void testAddText() throws Exception { 82 File dir = getEmptyDir("testAddText"); 83 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 84 Looper.getMainLooper()); 85 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 86 87 long before = System.currentTimeMillis(); 88 Thread.sleep(5); 89 dropbox.addText("DropBoxTest", "TEST0"); 90 Thread.sleep(5); 91 long between = System.currentTimeMillis(); 92 Thread.sleep(5); 93 dropbox.addText("DropBoxTest", "TEST1"); 94 dropbox.addText("DropBoxTest", "TEST2"); 95 Thread.sleep(5); 96 long after = System.currentTimeMillis(); 97 98 DropBoxManager.Entry e0 = dropbox.getNextEntry("DropBoxTest", before); 99 DropBoxManager.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis()); 100 DropBoxManager.Entry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis()); 101 assertTrue(null == dropbox.getNextEntry("DropBoxTest", e2.getTimeMillis())); 102 103 assertTrue(e0.getTimeMillis() > before); 104 assertTrue(e0.getTimeMillis() < between); 105 assertTrue(e1.getTimeMillis() > between); 106 assertTrue(e1.getTimeMillis() < e2.getTimeMillis()); 107 assertTrue(e2.getTimeMillis() < after); 108 109 assertEquals("TEST0", e0.getText(80)); 110 assertEquals("TEST1", e1.getText(80)); 111 assertEquals("TES", e2.getText(3)); 112 113 e0.close(); 114 e1.close(); 115 e2.close(); 116 } 117 118 public void testAddData() throws Exception { 119 File dir = getEmptyDir("testAddData"); 120 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 121 Looper.getMainLooper()); 122 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 123 124 long before = System.currentTimeMillis(); 125 Thread.sleep(1); 126 dropbox.addData("DropBoxTest", "TEST".getBytes(), 0); 127 Thread.sleep(1); 128 long after = System.currentTimeMillis(); 129 130 DropBoxManager.Entry e = dropbox.getNextEntry("DropBoxTest", before); 131 assertNotNull(e); 132 assertNull(dropbox.getNextEntry("DropBoxTest", e.getTimeMillis())); 133 134 assertEquals("DropBoxTest", e.getTag()); 135 assertTrue(e.getTimeMillis() >= before); 136 assertEquals(0, e.getFlags()); 137 assertTrue(null == e.getText(80)); 138 139 byte[] buf = new byte[80]; 140 assertEquals("TEST", new String(buf, 0, e.getInputStream().read(buf))); 141 142 e.close(); 143 } 144 145 public void testAddFile() throws Exception { 146 File dir = getEmptyDir("testAddFile"); 147 long before = System.currentTimeMillis(); 148 149 File clientDir = getEmptyDir("testAddFile_client"); 150 151 File f0 = new File(clientDir, "f0.txt"); 152 File f1 = new File(clientDir, "f1.txt.gz"); 153 File f2 = new File(clientDir, "f2.dat"); 154 File f3 = new File(clientDir, "f2.dat.gz"); 155 156 FileWriter w0 = new FileWriter(f0); 157 GZIPOutputStream gz1 = new GZIPOutputStream(new FileOutputStream(f1)); 158 FileOutputStream os2 = new FileOutputStream(f2); 159 GZIPOutputStream gz3 = new GZIPOutputStream(new FileOutputStream(f3)); 160 161 w0.write("FILE0"); 162 gz1.write("FILE1".getBytes()); 163 os2.write("DATA2".getBytes()); 164 gz3.write("DATA3".getBytes()); 165 166 w0.close(); 167 gz1.close(); 168 os2.close(); 169 gz3.close(); 170 171 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 172 Looper.getMainLooper()); 173 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 174 175 dropbox.addFile("DropBoxTest", f0, DropBoxManager.IS_TEXT); 176 dropbox.addFile("DropBoxTest", f1, DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED); 177 dropbox.addFile("DropBoxTest", f2, 0); 178 dropbox.addFile("DropBoxTest", f3, DropBoxManager.IS_GZIPPED); 179 180 DropBoxManager.Entry e0 = dropbox.getNextEntry("DropBoxTest", before); 181 DropBoxManager.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis()); 182 DropBoxManager.Entry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis()); 183 DropBoxManager.Entry e3 = dropbox.getNextEntry("DropBoxTest", e2.getTimeMillis()); 184 assertTrue(null == dropbox.getNextEntry("DropBoxTest", e3.getTimeMillis())); 185 186 assertTrue(e0.getTimeMillis() > before); 187 assertTrue(e1.getTimeMillis() > e0.getTimeMillis()); 188 assertTrue(e2.getTimeMillis() > e1.getTimeMillis()); 189 assertTrue(e3.getTimeMillis() > e2.getTimeMillis()); 190 191 assertEquals(DropBoxManager.IS_TEXT, e0.getFlags()); 192 assertEquals(DropBoxManager.IS_TEXT, e1.getFlags()); 193 assertEquals(0, e2.getFlags()); 194 assertEquals(0, e3.getFlags()); 195 196 assertEquals("FILE0", e0.getText(80)); 197 198 byte[] buf1 = new byte[80]; 199 assertEquals("FILE1", new String(buf1, 0, e1.getInputStream().read(buf1))); 200 201 assertTrue(null == e2.getText(80)); 202 byte[] buf2 = new byte[80]; 203 assertEquals("DATA2", new String(buf2, 0, e2.getInputStream().read(buf2))); 204 205 assertTrue(null == e3.getText(80)); 206 byte[] buf3 = new byte[80]; 207 assertEquals("DATA3", new String(buf3, 0, e3.getInputStream().read(buf3))); 208 209 e0.close(); 210 e1.close(); 211 e2.close(); 212 e3.close(); 213 } 214 testAddEntriesInTheFuture()215 public void testAddEntriesInTheFuture() throws Exception { 216 File dir = getEmptyDir("testAddEntriesInTheFuture"); 217 long before = System.currentTimeMillis(); 218 219 // Near future: should be allowed to persist 220 FileWriter w0 = new FileWriter(new File(dir, "DropBoxTest@" + (before + 5000) + ".txt")); 221 w0.write("FUTURE0"); 222 w0.close(); 223 224 // Far future: should be collapsed 225 FileWriter w1 = new FileWriter(new File(dir, "DropBoxTest@" + (before + 100000) + ".txt")); 226 w1.write("FUTURE1"); 227 w1.close(); 228 229 // Another far future item, this one gzipped 230 File f2 = new File(dir, "DropBoxTest@" + (before + 100001) + ".txt.gz"); 231 GZIPOutputStream gz2 = new GZIPOutputStream(new FileOutputStream(f2)); 232 gz2.write("FUTURE2".getBytes()); 233 gz2.close(); 234 235 // Tombstone in the far future 236 new FileOutputStream(new File(dir, "DropBoxTest@" + (before + 100002) + ".lost")).close(); 237 238 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 239 Looper.getMainLooper()); 240 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 241 242 // Until a write, the timestamps are taken at face value 243 DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before); 244 DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis()); 245 DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis()); 246 DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis()); 247 assertTrue(null == dropbox.getNextEntry(null, e3.getTimeMillis())); 248 249 assertEquals("FUTURE0", e0.getText(80)); 250 assertEquals("FUTURE1", e1.getText(80)); 251 assertEquals("FUTURE2", e2.getText(80)); 252 assertEquals(null, e3.getText(80)); 253 254 assertEquals(before + 5000, e0.getTimeMillis()); 255 assertEquals(before + 100000, e1.getTimeMillis()); 256 assertEquals(before + 100001, e2.getTimeMillis()); 257 assertEquals(before + 100002, e3.getTimeMillis()); 258 259 e0.close(); 260 e1.close(); 261 e2.close(); 262 e3.close(); 263 264 // Write something to force a collapse 265 dropbox.addText("NotDropBoxTest", "FUTURE"); 266 e0 = dropbox.getNextEntry(null, before); 267 e1 = dropbox.getNextEntry(null, e0.getTimeMillis()); 268 e2 = dropbox.getNextEntry(null, e1.getTimeMillis()); 269 e3 = dropbox.getNextEntry(null, e2.getTimeMillis()); 270 assertTrue(null == dropbox.getNextEntry("DropBoxTest", e3.getTimeMillis())); 271 272 assertEquals("FUTURE0", e0.getText(80)); 273 assertEquals("FUTURE1", e1.getText(80)); 274 assertEquals("FUTURE2", e2.getText(80)); 275 assertEquals(null, e3.getText(80)); 276 277 assertEquals(before + 5000, e0.getTimeMillis()); 278 assertEquals(before + 5001, e1.getTimeMillis()); 279 assertEquals(before + 5002, e2.getTimeMillis()); 280 assertEquals(before + 5003, e3.getTimeMillis()); 281 282 e0.close(); 283 e1.close(); 284 e2.close(); 285 e3.close(); 286 } 287 testIsTagEnabled()288 public void testIsTagEnabled() throws Exception { 289 File dir = getEmptyDir("testIsTagEnabled"); 290 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 291 Looper.getMainLooper()); 292 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 293 294 long before = System.currentTimeMillis(); 295 dropbox.addText("DropBoxTest", "TEST-ENABLED"); 296 assertTrue(dropbox.isTagEnabled("DropBoxTest")); 297 298 ContentResolver cr = getContext().getContentResolver(); 299 Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest", 300 "disabled"); 301 302 dropbox.addText("DropBoxTest", "TEST-DISABLED"); 303 assertFalse(dropbox.isTagEnabled("DropBoxTest")); 304 305 Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest", 306 ""); 307 308 dropbox.addText("DropBoxTest", "TEST-ENABLED-AGAIN"); 309 assertTrue(dropbox.isTagEnabled("DropBoxTest")); 310 311 DropBoxManager.Entry e0 = dropbox.getNextEntry("DropBoxTest", before); 312 DropBoxManager.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis()); 313 assertTrue(null == dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis())); 314 315 assertEquals("TEST-ENABLED", e0.getText(80)); 316 assertEquals("TEST-ENABLED-AGAIN", e1.getText(80)); 317 318 e0.close(); 319 e1.close(); 320 } 321 testGetNextEntry()322 public void testGetNextEntry() throws Exception { 323 File dir = getEmptyDir("testGetNextEntry"); 324 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 325 Looper.getMainLooper()); 326 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 327 328 long before = System.currentTimeMillis(); 329 dropbox.addText("DropBoxTest.A", "A0"); 330 dropbox.addText("DropBoxTest.B", "B0"); 331 dropbox.addText("DropBoxTest.A", "A1"); 332 333 DropBoxManager.Entry a0 = dropbox.getNextEntry("DropBoxTest.A", before); 334 DropBoxManager.Entry a1 = dropbox.getNextEntry("DropBoxTest.A", a0.getTimeMillis()); 335 assertTrue(null == dropbox.getNextEntry("DropBoxTest.A", a1.getTimeMillis())); 336 337 DropBoxManager.Entry b0 = dropbox.getNextEntry("DropBoxTest.B", before); 338 assertTrue(null == dropbox.getNextEntry("DropBoxTest.B", b0.getTimeMillis())); 339 340 DropBoxManager.Entry x0 = dropbox.getNextEntry(null, before); 341 DropBoxManager.Entry x1 = dropbox.getNextEntry(null, x0.getTimeMillis()); 342 DropBoxManager.Entry x2 = dropbox.getNextEntry(null, x1.getTimeMillis()); 343 assertTrue(null == dropbox.getNextEntry(null, x2.getTimeMillis())); 344 345 assertEquals("DropBoxTest.A", a0.getTag()); 346 assertEquals("DropBoxTest.A", a1.getTag()); 347 assertEquals("A0", a0.getText(80)); 348 assertEquals("A1", a1.getText(80)); 349 350 assertEquals("DropBoxTest.B", b0.getTag()); 351 assertEquals("B0", b0.getText(80)); 352 353 assertEquals("DropBoxTest.A", x0.getTag()); 354 assertEquals("DropBoxTest.B", x1.getTag()); 355 assertEquals("DropBoxTest.A", x2.getTag()); 356 assertEquals("A0", x0.getText(80)); 357 assertEquals("B0", x1.getText(80)); 358 assertEquals("A1", x2.getText(80)); 359 360 a0.close(); 361 a1.close(); 362 b0.close(); 363 x0.close(); 364 x1.close(); 365 x2.close(); 366 } 367 testSizeLimits()368 public void testSizeLimits() throws Exception { 369 File dir = getEmptyDir("testSizeLimits"); 370 int blockSize = new StatFs(dir.getPath()).getBlockSize(); 371 372 // Limit storage to 10 blocks 373 int kb = blockSize * 10 / 1024; 374 ContentResolver cr = getContext().getContentResolver(); 375 Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, Integer.toString(kb)); 376 377 // Three tags using a total of 12 blocks: 378 // DropBoxTest0 [ ][ ] 379 // DropBoxTest1 [x][ ][ ][ ][xxx(20 blocks)xxx] 380 // DropBoxTest2 [xxxxxxxxxx][ ][ ] 381 // 382 // The blocks marked "x" will be removed due to storage restrictions. 383 // Use random fill (so it doesn't compress), subtract a little for gzip overhead 384 385 final int overhead = 64; 386 long before = System.currentTimeMillis(); 387 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 388 Looper.getMainLooper()); 389 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 390 391 addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead); 392 addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead); 393 394 addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead); 395 addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead); 396 addRandomEntry(dropbox, "DropBoxTest1", blockSize * 2 - overhead); 397 addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead); 398 addRandomEntry(dropbox, "DropBoxTest1", blockSize * 20 - overhead); 399 400 addRandomEntry(dropbox, "DropBoxTest2", blockSize * 4 - overhead); 401 addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead); 402 addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead); 403 404 DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before); 405 DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis()); 406 DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis()); 407 DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis()); 408 DropBoxManager.Entry e4 = dropbox.getNextEntry(null, e3.getTimeMillis()); 409 DropBoxManager.Entry e5 = dropbox.getNextEntry(null, e4.getTimeMillis()); 410 DropBoxManager.Entry e6 = dropbox.getNextEntry(null, e5.getTimeMillis()); 411 DropBoxManager.Entry e7 = dropbox.getNextEntry(null, e6.getTimeMillis()); 412 DropBoxManager.Entry e8 = dropbox.getNextEntry(null, e7.getTimeMillis()); 413 DropBoxManager.Entry e9 = dropbox.getNextEntry(null, e8.getTimeMillis()); 414 assertTrue(null == dropbox.getNextEntry(null, e9.getTimeMillis())); 415 416 assertEquals("DropBoxTest0", e0.getTag()); 417 assertEquals("DropBoxTest0", e1.getTag()); 418 assertEquals(blockSize - overhead, getEntrySize(e0)); 419 assertEquals(blockSize - overhead, getEntrySize(e1)); 420 421 assertEquals("DropBoxTest1", e2.getTag()); 422 assertEquals("DropBoxTest1", e3.getTag()); 423 assertEquals("DropBoxTest1", e4.getTag()); 424 assertEquals("DropBoxTest1", e5.getTag()); 425 assertEquals("DropBoxTest1", e6.getTag()); 426 assertEquals(-1, getEntrySize(e2)); // Tombstone 427 assertEquals(blockSize - overhead, getEntrySize(e3)); 428 assertEquals(blockSize * 2 - overhead, getEntrySize(e4)); 429 assertEquals(blockSize - overhead, getEntrySize(e5)); 430 assertEquals(-1, getEntrySize(e6)); 431 432 assertEquals("DropBoxTest2", e7.getTag()); 433 assertEquals("DropBoxTest2", e8.getTag()); 434 assertEquals("DropBoxTest2", e9.getTag()); 435 assertEquals(-1, getEntrySize(e7)); // Tombstone 436 assertEquals(blockSize - overhead, getEntrySize(e8)); 437 assertEquals(blockSize - overhead, getEntrySize(e9)); 438 439 e0.close(); 440 e1.close(); 441 e2.close(); 442 e3.close(); 443 e4.close(); 444 e5.close(); 445 e6.close(); 446 e7.close(); 447 e8.close(); 448 e9.close(); 449 450 // Specifying a tag name skips tombstone records. 451 452 DropBoxManager.Entry t0 = dropbox.getNextEntry("DropBoxTest1", before); 453 DropBoxManager.Entry t1 = dropbox.getNextEntry("DropBoxTest1", t0.getTimeMillis()); 454 DropBoxManager.Entry t2 = dropbox.getNextEntry("DropBoxTest1", t1.getTimeMillis()); 455 assertTrue(null == dropbox.getNextEntry("DropBoxTest1", t2.getTimeMillis())); 456 457 assertEquals("DropBoxTest1", t0.getTag()); 458 assertEquals("DropBoxTest1", t1.getTag()); 459 assertEquals("DropBoxTest1", t2.getTag()); 460 461 assertEquals(blockSize - overhead, getEntrySize(t0)); 462 assertEquals(blockSize * 2 - overhead, getEntrySize(t1)); 463 assertEquals(blockSize - overhead, getEntrySize(t2)); 464 465 t0.close(); 466 t1.close(); 467 t2.close(); 468 } 469 testAgeLimits()470 public void testAgeLimits() throws Exception { 471 File dir = getEmptyDir("testAgeLimits"); 472 int blockSize = new StatFs(dir.getPath()).getBlockSize(); 473 474 // Limit storage to 10 blocks with an expiration of 1 second 475 int kb = blockSize * 10 / 1024; 476 ContentResolver cr = getContext().getContentResolver(); 477 Settings.Global.putString(cr, Settings.Global.DROPBOX_AGE_SECONDS, "1"); 478 Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, Integer.toString(kb)); 479 480 // Write one normal entry and another so big that it is instantly tombstoned 481 long before = System.currentTimeMillis(); 482 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 483 Looper.getMainLooper()); 484 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 485 486 dropbox.addText("DropBoxTest", "TEST"); 487 addRandomEntry(dropbox, "DropBoxTest", blockSize * 20); 488 489 // Verify that things are as expected 490 DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before); 491 DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis()); 492 assertTrue(null == dropbox.getNextEntry(null, e1.getTimeMillis())); 493 494 assertEquals("TEST", e0.getText(80)); 495 assertEquals(null, e1.getText(80)); 496 assertEquals(-1, getEntrySize(e1)); 497 498 e0.close(); 499 e1.close(); 500 501 // Wait a second and write another entry -- old ones should be expunged 502 Thread.sleep(2000); 503 dropbox.addText("DropBoxTest", "TEST1"); 504 505 e0 = dropbox.getNextEntry(null, before); 506 assertTrue(null == dropbox.getNextEntry(null, e0.getTimeMillis())); 507 assertEquals("TEST1", e0.getText(80)); 508 e0.close(); 509 } 510 testFileCountLimits()511 public void testFileCountLimits() throws Exception { 512 File dir = getEmptyDir("testFileCountLimits"); 513 514 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 515 Looper.getMainLooper()); 516 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 517 dropbox.addText("DropBoxTest", "TEST0"); 518 dropbox.addText("DropBoxTest", "TEST1"); 519 dropbox.addText("DropBoxTest", "TEST2"); 520 dropbox.addText("DropBoxTest", "TEST3"); 521 dropbox.addText("DropBoxTest", "TEST4"); 522 dropbox.addText("DropBoxTest", "TEST5"); 523 524 // Verify 6 files added 525 DropBoxManager.Entry e0 = dropbox.getNextEntry(null, 0); 526 DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis()); 527 DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis()); 528 DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis()); 529 DropBoxManager.Entry e4 = dropbox.getNextEntry(null, e3.getTimeMillis()); 530 DropBoxManager.Entry e5 = dropbox.getNextEntry(null, e4.getTimeMillis()); 531 assertTrue(null == dropbox.getNextEntry(null, e5.getTimeMillis())); 532 assertEquals("TEST0", e0.getText(80)); 533 assertEquals("TEST5", e5.getText(80)); 534 535 e0.close(); 536 e1.close(); 537 e2.close(); 538 e3.close(); 539 e4.close(); 540 e5.close(); 541 542 // Limit to 3 files and add one more entry 543 ContentResolver cr = getContext().getContentResolver(); 544 Settings.Global.putString(cr, Settings.Global.DROPBOX_MAX_FILES, "3"); 545 dropbox.addText("DropBoxTest", "TEST6"); 546 547 // Verify only 3 files left 548 DropBoxManager.Entry f0 = dropbox.getNextEntry(null, 0); 549 DropBoxManager.Entry f1 = dropbox.getNextEntry(null, f0.getTimeMillis()); 550 DropBoxManager.Entry f2 = dropbox.getNextEntry(null, f1.getTimeMillis()); 551 assertTrue(null == dropbox.getNextEntry(null, f2.getTimeMillis())); 552 assertEquals("TEST4", f0.getText(80)); 553 assertEquals("TEST5", f1.getText(80)); 554 assertEquals("TEST6", f2.getText(80)); 555 556 f0.close(); 557 f1.close(); 558 f2.close(); 559 } 560 testCreateDropBoxManagerWithInvalidDirectory()561 public void testCreateDropBoxManagerWithInvalidDirectory() throws Exception { 562 // If created with an invalid directory, the DropBoxManager should suffer quietly 563 // and fail all operations (this is how it survives a full disk). 564 // Once the directory becomes possible to create, it will start working. 565 566 File dir = new File(getEmptyDir("testCreateDropBoxManagerWith"), "InvalidDirectory"); 567 new FileOutputStream(dir).close(); // Create an empty file 568 DropBoxManagerService service = new DropBoxManagerService(getContext(), dir, 569 Looper.getMainLooper()); 570 DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub()); 571 572 dropbox.addText("DropBoxTest", "should be ignored"); 573 dropbox.addData("DropBoxTest", "should be ignored".getBytes(), 0); 574 assertTrue(null == dropbox.getNextEntry("DropBoxTest", 0)); 575 576 dir.delete(); // Remove the file so a directory can be created 577 dropbox.addText("DropBoxTest", "TEST"); 578 DropBoxManager.Entry e = dropbox.getNextEntry("DropBoxTest", 0); 579 assertTrue(null == dropbox.getNextEntry("DropBoxTest", e.getTimeMillis())); 580 assertEquals("DropBoxTest", e.getTag()); 581 assertEquals("TEST", e.getText(80)); 582 e.close(); 583 } 584 testDropBoxEntrySerialization()585 public void testDropBoxEntrySerialization() throws Exception { 586 // Make sure DropBoxManager.Entry can be serialized to a Parcel and back 587 // under a variety of conditions. 588 589 Parcel parcel = Parcel.obtain(); 590 File dir = getEmptyDir("testDropBoxEntrySerialization"); 591 592 new DropBoxManager.Entry("empty", 1000000).writeToParcel(parcel, 0); 593 new DropBoxManager.Entry("string", 2000000, "String Value").writeToParcel(parcel, 0); 594 new DropBoxManager.Entry("bytes", 3000000, "Bytes Value".getBytes(), 595 DropBoxManager.IS_TEXT).writeToParcel(parcel, 0); 596 new DropBoxManager.Entry("zerobytes", 4000000, new byte[0], 0).writeToParcel(parcel, 0); 597 new DropBoxManager.Entry("emptybytes", 5000000, (byte[]) null, 598 DropBoxManager.IS_EMPTY).writeToParcel(parcel, 0); 599 600 try { 601 new DropBoxManager.Entry("badbytes", 99999, 602 "Bad Bytes Value".getBytes(), 603 DropBoxManager.IS_EMPTY).writeToParcel(parcel, 0); 604 fail("IllegalArgumentException expected for non-null byte[] and IS_EMPTY flags"); 605 } catch (IllegalArgumentException e) { 606 // expected 607 } 608 609 try { 610 new DropBoxManager.Entry("badbytes", 99999, (byte[]) null, 0).writeToParcel(parcel, 0); 611 fail("IllegalArgumentException expected for null byte[] and non-IS_EMPTY flags"); 612 } catch (IllegalArgumentException e) { 613 // expected 614 } 615 616 File f = new File(dir, "file.dat"); 617 FileOutputStream os = new FileOutputStream(f); 618 os.write("File Value".getBytes()); 619 os.close(); 620 621 new DropBoxManager.Entry("file", 6000000, f, DropBoxManager.IS_TEXT).writeToParcel( 622 parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 623 new DropBoxManager.Entry("binfile", 7000000, f, 0).writeToParcel( 624 parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 625 new DropBoxManager.Entry("emptyfile", 8000000, (ParcelFileDescriptor) null, 626 DropBoxManager.IS_EMPTY).writeToParcel(parcel, 0); 627 628 try { 629 new DropBoxManager.Entry("badfile", 99999, new File(dir, "nonexist.dat"), 0); 630 fail("IOException expected for nonexistent file"); 631 } catch (IOException e) { 632 // expected 633 } 634 635 try { 636 new DropBoxManager.Entry("badfile", 99999, f, DropBoxManager.IS_EMPTY).writeToParcel( 637 parcel, 0); 638 fail("IllegalArgumentException expected for non-null file and IS_EMPTY flags"); 639 } catch (IllegalArgumentException e) { 640 // expected 641 } 642 643 try { 644 new DropBoxManager.Entry("badfile", 99999, (ParcelFileDescriptor) null, 0); 645 fail("IllegalArgumentException expected for null PFD and non-IS_EMPTY flags"); 646 } catch (IllegalArgumentException e) { 647 // expected 648 } 649 650 File gz = new File(dir, "file.gz"); 651 GZIPOutputStream gzout = new GZIPOutputStream(new FileOutputStream(gz)); 652 gzout.write("Gzip File Value".getBytes()); 653 gzout.close(); 654 655 new DropBoxManager.Entry("gzipfile", 9000000, gz, 656 DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED).writeToParcel( 657 parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 658 new DropBoxManager.Entry("gzipbinfile", 10000000, gz, 659 DropBoxManager.IS_GZIPPED).writeToParcel( 660 parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 661 662 // 663 // Switch from writing to reading 664 // 665 666 parcel.setDataPosition(0); 667 DropBoxManager.Entry e; 668 669 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 670 assertEquals("empty", e.getTag()); 671 assertEquals(1000000, e.getTimeMillis()); 672 assertEquals(DropBoxManager.IS_EMPTY, e.getFlags()); 673 assertEquals(null, e.getText(100)); 674 assertEquals(null, e.getInputStream()); 675 e.close(); 676 677 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 678 assertEquals("string", e.getTag()); 679 assertEquals(2000000, e.getTimeMillis()); 680 assertEquals(DropBoxManager.IS_TEXT, e.getFlags()); 681 assertEquals("String Value", e.getText(100)); 682 assertEquals("String Value", 683 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine()); 684 e.close(); 685 686 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 687 assertEquals("bytes", e.getTag()); 688 assertEquals(3000000, e.getTimeMillis()); 689 assertEquals(DropBoxManager.IS_TEXT, e.getFlags()); 690 assertEquals("Bytes Value", e.getText(100)); 691 e.close(); 692 693 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 694 assertEquals("zerobytes", e.getTag()); 695 assertEquals(4000000, e.getTimeMillis()); 696 assertEquals(0, e.getFlags()); 697 assertEquals(null, e.getText(100)); 698 assertEquals(null, 699 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine()); 700 e.close(); 701 702 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 703 assertEquals("emptybytes", e.getTag()); 704 assertEquals(5000000, e.getTimeMillis()); 705 assertEquals(DropBoxManager.IS_EMPTY, e.getFlags()); 706 assertEquals(null, e.getText(100)); 707 assertEquals(null, e.getInputStream()); 708 e.close(); 709 710 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 711 assertEquals("file", e.getTag()); 712 assertEquals(6000000, e.getTimeMillis()); 713 assertEquals(DropBoxManager.IS_TEXT, e.getFlags()); 714 assertEquals("File Value", e.getText(100)); 715 e.close(); 716 717 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 718 assertEquals("binfile", e.getTag()); 719 assertEquals(7000000, e.getTimeMillis()); 720 assertEquals(0, e.getFlags()); 721 assertEquals(null, e.getText(100)); 722 assertEquals("File Value", 723 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine()); 724 e.close(); 725 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 726 assertEquals("emptyfile", e.getTag()); 727 assertEquals(8000000, e.getTimeMillis()); 728 assertEquals(DropBoxManager.IS_EMPTY, e.getFlags()); 729 assertEquals(null, e.getText(100)); 730 assertEquals(null, e.getInputStream()); 731 e.close(); 732 733 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 734 assertEquals("gzipfile", e.getTag()); 735 assertEquals(9000000, e.getTimeMillis()); 736 assertEquals(DropBoxManager.IS_TEXT, e.getFlags()); 737 assertEquals("Gzip File Value", e.getText(100)); 738 e.close(); 739 740 e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 741 assertEquals("gzipbinfile", e.getTag()); 742 assertEquals(10000000, e.getTimeMillis()); 743 assertEquals(0, e.getFlags()); 744 assertEquals(null, e.getText(100)); 745 assertEquals("Gzip File Value", 746 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine()); 747 e.close(); 748 assertEquals(0, parcel.dataAvail()); 749 parcel.recycle(); 750 } 751 testDropBoxEntrySerializationDoesntLeakFileDescriptors()752 public void testDropBoxEntrySerializationDoesntLeakFileDescriptors() throws Exception { 753 File dir = getEmptyDir("testDropBoxEntrySerialization"); 754 File f = new File(dir, "file.dat"); 755 FileOutputStream os = new FileOutputStream(f); 756 os.write("File Value".getBytes()); 757 os.close(); 758 759 int before = countOpenFiles(); 760 assertTrue(before > 0); 761 762 for (int i = 0; i < 1000; i++) { 763 Parcel parcel = Parcel.obtain(); 764 new DropBoxManager.Entry("file", 1000000, f, 0).writeToParcel( 765 parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 766 767 parcel.setDataPosition(0); 768 DropBoxManager.Entry e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel); 769 assertEquals("file", e.getTag()); 770 e.close(); 771 772 parcel.recycle(); 773 } 774 775 int after = countOpenFiles(); 776 assertTrue(after > 0); 777 assertTrue(after < before + 20); 778 } 779 780 public void testEntryFile() throws Exception { 781 File fromDir = getEmptyDir("testEntryFile_from"); 782 File toDir = getEmptyDir("testEntryFile_to"); 783 784 { 785 File f = new File(fromDir, "f0.txt"); 786 try (FileWriter w = new FileWriter(f)) { 787 w.write("abc"); 788 } 789 790 EntryFile e = new EntryFile(f, toDir, "tag:!", 12345, DropBoxManager.IS_TEXT, 1024); 791 792 assertEquals("tag:!", e.tag); 793 assertEquals(12345, e.timestampMillis); 794 assertEquals(DropBoxManager.IS_TEXT, e.flags); 795 assertEquals(1, e.blocks); 796 797 assertFalse(f.exists()); // Because it should be renamed. 798 799 assertTrue(e.hasFile()); 800 assertEquals(new File(toDir, "tag%3A!@12345.txt"), e.getFile(toDir)); 801 assertTrue(e.getFile(toDir).exists()); 802 } 803 // Same test with gzip. 804 { 805 File f = new File(fromDir, "f0.txt.gz"); // It's a lie; it's not actually gz. 806 try (FileWriter w = new FileWriter(f)) { 807 w.write("abc"); 808 } 809 810 EntryFile e = new EntryFile(f, toDir, "tag:!", 12345, 811 DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED, 1024); 812 813 assertEquals("tag:!", e.tag); 814 815 assertFalse(f.exists()); // Because it should be renamed. 816 817 assertTrue(e.hasFile()); 818 assertEquals(new File(toDir, "tag%3A!@12345.txt.gz"), e.getFile(toDir)); 819 assertTrue(e.getFile(toDir).exists()); 820 821 } 822 // binary, gzip. 823 { 824 File f = new File(fromDir, "f0.dat.gz"); // It's a lie; it's not actually gz. 825 try (FileWriter w = new FileWriter(f)) { 826 w.write("abc"); 827 } 828 829 EntryFile e = new EntryFile(f, toDir, "tag:!", 12345, 830 DropBoxManager.IS_GZIPPED, 1024); 831 832 assertEquals("tag:!", e.tag); 833 834 assertFalse(f.exists()); // Because it should be renamed. 835 836 assertTrue(e.hasFile()); 837 assertEquals(new File(toDir, "tag%3A!@12345.dat.gz"), e.getFile(toDir)); 838 assertTrue(e.getFile(toDir).exists()); 839 840 } 841 842 // Tombstone. 843 { 844 EntryFile e = new EntryFile(toDir, "tag:!", 12345); 845 846 assertEquals("tag:!", e.tag); 847 assertEquals(12345, e.timestampMillis); 848 assertEquals(DropBoxManager.IS_EMPTY, e.flags); 849 assertEquals(0, e.blocks); 850 851 assertTrue(e.hasFile()); 852 assertEquals(new File(toDir, "tag%3A!@12345.lost"), e.getFile(toDir)); 853 assertTrue(e.getFile(toDir).exists()); 854 } 855 856 // From existing files. 857 { 858 File f = new File(fromDir, "tag%3A!@12345.dat"); 859 f.createNewFile(); 860 861 EntryFile e = new EntryFile(f, 1024); 862 863 assertEquals("tag:!", e.tag); 864 assertEquals(12345, e.timestampMillis); 865 assertEquals(0, e.flags); 866 assertEquals(0, e.blocks); 867 868 assertTrue(f.exists()); 869 } 870 { 871 File f = new File(fromDir, "tag%3A!@12345.dat.gz"); 872 f.createNewFile(); 873 874 EntryFile e = new EntryFile(f, 1024); 875 876 assertEquals("tag:!", e.tag); 877 assertEquals(12345, e.timestampMillis); 878 assertEquals(DropBoxManager.IS_GZIPPED, e.flags); 879 assertEquals(0, e.blocks); 880 881 assertTrue(f.exists()); 882 } 883 { 884 File f = new File(fromDir, "tag%3A!@12345.txt"); 885 try (FileWriter w = new FileWriter(f)) { 886 w.write(new char[1024]); 887 } 888 889 EntryFile e = new EntryFile(f, 1024); 890 891 assertEquals("tag:!", e.tag); 892 assertEquals(12345, e.timestampMillis); 893 assertEquals(DropBoxManager.IS_TEXT, e.flags); 894 assertEquals(1, e.blocks); 895 896 assertTrue(f.exists()); 897 } 898 { 899 File f = new File(fromDir, "tag%3A!@12345.txt.gz"); 900 try (FileWriter w = new FileWriter(f)) { 901 w.write(new char[1025]); 902 } 903 904 EntryFile e = new EntryFile(f, 1024); 905 906 assertEquals("tag:!", e.tag); 907 assertEquals(12345, e.timestampMillis); 908 assertEquals(DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED, e.flags); 909 assertEquals(2, e.blocks); 910 911 assertTrue(f.exists()); 912 } 913 { 914 File f = new File(fromDir, "tag%3A!@12345.lost"); 915 f.createNewFile(); 916 917 EntryFile e = new EntryFile(f, 1024); 918 919 assertEquals("tag:!", e.tag); 920 assertEquals(12345, e.timestampMillis); 921 assertEquals(DropBoxManager.IS_EMPTY, e.flags); 922 assertEquals(0, e.blocks); 923 924 assertTrue(f.exists()); 925 } 926 { 927 File f = new File(fromDir, "@12345.dat"); // Empty tag -- this actually works. 928 f.createNewFile(); 929 930 EntryFile e = new EntryFile(f, 1024); 931 932 assertEquals("", e.tag); 933 assertEquals(12345, e.timestampMillis); 934 assertEquals(0, e.flags); 935 assertEquals(0, e.blocks); 936 937 assertTrue(f.exists()); 938 } 939 // From invalid filenames. 940 { 941 File f = new File(fromDir, "tag.dat"); // No @. 942 f.createNewFile(); 943 944 EntryFile e = new EntryFile(f, 1024); 945 946 assertEquals(null, e.tag); 947 assertEquals(0, e.timestampMillis); 948 assertEquals(DropBoxManager.IS_EMPTY, e.flags); 949 assertEquals(0, e.blocks); 950 951 assertFalse(f.exists()); 952 } 953 { 954 File f = new File(fromDir, "tag@.dat"); // Invalid timestamp. 955 f.createNewFile(); 956 957 EntryFile e = new EntryFile(f, 1024); 958 959 assertEquals(null, e.tag); 960 assertEquals(0, e.timestampMillis); 961 assertEquals(DropBoxManager.IS_EMPTY, e.flags); 962 assertEquals(0, e.blocks); 963 964 assertFalse(f.exists()); 965 } 966 { 967 File f = new File(fromDir, "tag@12345.daxt"); // Invalid extension. 968 f.createNewFile(); 969 970 EntryFile e = new EntryFile(f, 1024); 971 972 assertEquals(null, e.tag); 973 assertEquals(0, e.timestampMillis); 974 assertEquals(DropBoxManager.IS_EMPTY, e.flags); 975 assertEquals(0, e.blocks); 976 977 assertFalse(f.exists()); 978 } 979 } 980 981 public void testCompareEntries() { 982 File dir = getEmptyDir("testCompareEntries"); 983 assertEquals(-1, 984 new EntryFile(new File(dir, "aaa@100.dat"), 1).compareTo( 985 new EntryFile(new File(dir, "bbb@200.dat"), 1))); 986 assertEquals(1, 987 new EntryFile(new File(dir, "aaa@200.dat"), 1).compareTo( 988 new EntryFile(new File(dir, "bbb@100.dat"), 1))); 989 assertEquals(-1, 990 new EntryFile(new File(dir, "aaa@100.dat"), 1).compareTo( 991 new EntryFile(new File(dir, "bbb@100.dat"), 1))); 992 assertEquals(1, 993 new EntryFile(new File(dir, "bbb@100.dat"), 1).compareTo( 994 new EntryFile(new File(dir, "aaa@100.dat"), 1))); 995 } 996 997 private void addRandomEntry(DropBoxManager dropbox, String tag, int size) throws Exception { 998 byte[] bytes = new byte[size]; 999 new Random(System.currentTimeMillis()).nextBytes(bytes); 1000 1001 File f = new File(getEmptyDir("addRandomEntry"), "random.dat"); 1002 FileOutputStream os = new FileOutputStream(f); 1003 os.write(bytes); 1004 os.close(); 1005 1006 dropbox.addFile(tag, f, 0); 1007 } 1008 1009 private int getEntrySize(DropBoxManager.Entry e) throws Exception { 1010 InputStream is = e.getInputStream(); 1011 if (is == null) return -1; 1012 int length = 0; 1013 while (is.read() != -1) length++; 1014 return length; 1015 } 1016 1017 private void recursiveDelete(File file) { 1018 if (!file.delete() && file.isDirectory()) { 1019 for (File f : file.listFiles()) recursiveDelete(f); 1020 file.delete(); 1021 } 1022 } 1023 1024 private File getEmptyDir(String name) { 1025 File dir = getContext().getDir("DropBoxTest." + name, 0); 1026 for (File f : dir.listFiles()) recursiveDelete(f); 1027 assertTrue(dir.listFiles().length == 0); 1028 return dir; 1029 } 1030 1031 private int countOpenFiles() { 1032 return new File("/proc/" + Process.myPid() + "/fd").listFiles().length; 1033 } 1034 } 1035