Home | History | Annotate | Download | only in server
      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
     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 
     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
     77     public Context getContext() {
     78         return mContext;
     79     }
     80 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 (at) 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 (at) 100.dat"), 1).compareTo(
    985                 new EntryFile(new File(dir, "bbb (at) 200.dat"), 1)));
    986         assertEquals(1,
    987                 new EntryFile(new File(dir, "aaa (at) 200.dat"), 1).compareTo(
    988                 new EntryFile(new File(dir, "bbb (at) 100.dat"), 1)));
    989         assertEquals(-1,
    990                 new EntryFile(new File(dir, "aaa (at) 100.dat"), 1).compareTo(
    991                 new EntryFile(new File(dir, "bbb (at) 100.dat"), 1)));
    992         assertEquals(1,
    993                 new EntryFile(new File(dir, "bbb (at) 100.dat"), 1).compareTo(
    994                 new EntryFile(new File(dir, "aaa (at) 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