• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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