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.Intent;
22 import android.os.DropBoxManager;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.os.ParcelFileDescriptor;
26 import android.os.Process;
27 import android.os.ServiceManager;
28 import android.os.StatFs;
29 import android.provider.Settings;
30 import android.test.AndroidTestCase;
31 
32 import com.android.server.DropBoxManagerService;
33 
34 import java.io.BufferedReader;
35 import java.io.File;
36 import java.io.FileOutputStream;
37 import java.io.FileWriter;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.InputStreamReader;
41 import java.util.Random;
42 import java.util.zip.GZIPOutputStream;
43 
44 /** Test {@link DropBoxManager} functionality. */
45 public class DropBoxTest extends AndroidTestCase {
tearDown()46     public void tearDown() throws Exception {
47         ContentResolver cr = getContext().getContentResolver();
48         Settings.Global.putString(cr, Settings.Global.DROPBOX_AGE_SECONDS, "");
49         Settings.Global.putString(cr, Settings.Global.DROPBOX_MAX_FILES, "");
50         Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, "");
51         Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest", "");
52     }
53 
testAddText()54     public void testAddText() throws Exception {
55         File dir = getEmptyDir("testAddText");
56         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
57         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
58 
59         long before = System.currentTimeMillis();
60         Thread.sleep(5);
61         dropbox.addText("DropBoxTest", "TEST0");
62         Thread.sleep(5);
63         long between = System.currentTimeMillis();
64         Thread.sleep(5);
65         dropbox.addText("DropBoxTest", "TEST1");
66         dropbox.addText("DropBoxTest", "TEST2");
67         Thread.sleep(5);
68         long after = System.currentTimeMillis();
69 
70         DropBoxManager.Entry e0 = dropbox.getNextEntry("DropBoxTest", before);
71         DropBoxManager.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
72         DropBoxManager.Entry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis());
73         assertTrue(null == dropbox.getNextEntry("DropBoxTest", e2.getTimeMillis()));
74 
75         assertTrue(e0.getTimeMillis() > before);
76         assertTrue(e0.getTimeMillis() < between);
77         assertTrue(e1.getTimeMillis() > between);
78         assertTrue(e1.getTimeMillis() < e2.getTimeMillis());
79         assertTrue(e2.getTimeMillis() < after);
80 
81         assertEquals("TEST0", e0.getText(80));
82         assertEquals("TEST1", e1.getText(80));
83         assertEquals("TES", e2.getText(3));
84 
85         e0.close();
86         e1.close();
87         e2.close();
88     }
89 
90     public void testAddData() throws Exception {
91         File dir = getEmptyDir("testAddData");
92         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
93         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
94 
95         long before = System.currentTimeMillis();
96         dropbox.addData("DropBoxTest", "TEST".getBytes(), 0);
97         long after = System.currentTimeMillis();
98 
99         DropBoxManager.Entry e = dropbox.getNextEntry("DropBoxTest", before);
100         assertTrue(null == dropbox.getNextEntry("DropBoxTest", e.getTimeMillis()));
101 
102         assertEquals("DropBoxTest", e.getTag());
103         assertTrue(e.getTimeMillis() >= before);
104         assertEquals(0, e.getFlags());
105         assertTrue(null == e.getText(80));
106 
107         byte[] buf = new byte[80];
108         assertEquals("TEST", new String(buf, 0, e.getInputStream().read(buf)));
109 
110         e.close();
111     }
112 
113     public void testAddFile() throws Exception {
114         File dir = getEmptyDir("testAddFile");
115         long before = System.currentTimeMillis();
116 
117         File f0 = new File(dir, "f0.txt");
118         File f1 = new File(dir, "f1.txt.gz");
119         File f2 = new File(dir, "f2.dat");
120         File f3 = new File(dir, "f2.dat.gz");
121 
122         FileWriter w0 = new FileWriter(f0);
123         GZIPOutputStream gz1 = new GZIPOutputStream(new FileOutputStream(f1));
124         FileOutputStream os2 = new FileOutputStream(f2);
125         GZIPOutputStream gz3 = new GZIPOutputStream(new FileOutputStream(f3));
126 
127         w0.write("FILE0");
128         gz1.write("FILE1".getBytes());
129         os2.write("DATA2".getBytes());
130         gz3.write("DATA3".getBytes());
131 
132         w0.close();
133         gz1.close();
134         os2.close();
135         gz3.close();
136 
137         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
138         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
139 
140         dropbox.addFile("DropBoxTest", f0, DropBoxManager.IS_TEXT);
141         dropbox.addFile("DropBoxTest", f1, DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED);
142         dropbox.addFile("DropBoxTest", f2, 0);
143         dropbox.addFile("DropBoxTest", f3, DropBoxManager.IS_GZIPPED);
144 
145         DropBoxManager.Entry e0 = dropbox.getNextEntry("DropBoxTest", before);
146         DropBoxManager.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
147         DropBoxManager.Entry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis());
148         DropBoxManager.Entry e3 = dropbox.getNextEntry("DropBoxTest", e2.getTimeMillis());
149         assertTrue(null == dropbox.getNextEntry("DropBoxTest", e3.getTimeMillis()));
150 
151         assertTrue(e0.getTimeMillis() > before);
152         assertTrue(e1.getTimeMillis() > e0.getTimeMillis());
153         assertTrue(e2.getTimeMillis() > e1.getTimeMillis());
154         assertTrue(e3.getTimeMillis() > e2.getTimeMillis());
155 
156         assertEquals(DropBoxManager.IS_TEXT, e0.getFlags());
157         assertEquals(DropBoxManager.IS_TEXT, e1.getFlags());
158         assertEquals(0, e2.getFlags());
159         assertEquals(0, e3.getFlags());
160 
161         assertEquals("FILE0", e0.getText(80));
162 
163         byte[] buf1 = new byte[80];
164         assertEquals("FILE1", new String(buf1, 0, e1.getInputStream().read(buf1)));
165 
166         assertTrue(null == e2.getText(80));
167         byte[] buf2 = new byte[80];
168         assertEquals("DATA2", new String(buf2, 0, e2.getInputStream().read(buf2)));
169 
170         assertTrue(null == e3.getText(80));
171         byte[] buf3 = new byte[80];
172         assertEquals("DATA3", new String(buf3, 0, e3.getInputStream().read(buf3)));
173 
174         e0.close();
175         e1.close();
176         e2.close();
177         e3.close();
178     }
179 
testAddEntriesInTheFuture()180     public void testAddEntriesInTheFuture() throws Exception {
181         File dir = getEmptyDir("testAddEntriesInTheFuture");
182         long before = System.currentTimeMillis();
183 
184         // Near future: should be allowed to persist
185         FileWriter w0 = new FileWriter(new File(dir, "DropBoxTest@" + (before + 5000) + ".txt"));
186         w0.write("FUTURE0");
187         w0.close();
188 
189         // Far future: should be collapsed
190         FileWriter w1 = new FileWriter(new File(dir, "DropBoxTest@" + (before + 100000) + ".txt"));
191         w1.write("FUTURE1");
192         w1.close();
193 
194         // Another far future item, this one gzipped
195         File f2 = new File(dir, "DropBoxTest@" + (before + 100001) + ".txt.gz");
196         GZIPOutputStream gz2 = new GZIPOutputStream(new FileOutputStream(f2));
197         gz2.write("FUTURE2".getBytes());
198         gz2.close();
199 
200         // Tombstone in the far future
201         new FileOutputStream(new File(dir, "DropBoxTest@" + (before + 100002) + ".lost")).close();
202 
203         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
204         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
205 
206         // Until a write, the timestamps are taken at face value
207         DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before);
208         DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
209         DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
210         DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
211         assertTrue(null == dropbox.getNextEntry(null, e3.getTimeMillis()));
212 
213         assertEquals("FUTURE0", e0.getText(80));
214         assertEquals("FUTURE1", e1.getText(80));
215         assertEquals("FUTURE2", e2.getText(80));
216         assertEquals(null, e3.getText(80));
217 
218         assertEquals(before + 5000, e0.getTimeMillis());
219         assertEquals(before + 100000, e1.getTimeMillis());
220         assertEquals(before + 100001, e2.getTimeMillis());
221         assertEquals(before + 100002, e3.getTimeMillis());
222 
223         e0.close();
224         e1.close();
225         e2.close();
226         e3.close();
227 
228         // Write something to force a collapse
229         dropbox.addText("NotDropBoxTest", "FUTURE");
230         e0 = dropbox.getNextEntry(null, before);
231         e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
232         e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
233         e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
234         assertTrue(null == dropbox.getNextEntry("DropBoxTest", e3.getTimeMillis()));
235 
236         assertEquals("FUTURE0", e0.getText(80));
237         assertEquals("FUTURE1", e1.getText(80));
238         assertEquals("FUTURE2", e2.getText(80));
239         assertEquals(null, e3.getText(80));
240 
241         assertEquals(before + 5000, e0.getTimeMillis());
242         assertEquals(before + 5001, e1.getTimeMillis());
243         assertEquals(before + 5002, e2.getTimeMillis());
244         assertEquals(before + 5003, e3.getTimeMillis());
245 
246         e0.close();
247         e1.close();
248         e2.close();
249         e3.close();
250     }
251 
testIsTagEnabled()252     public void testIsTagEnabled() throws Exception {
253         File dir = getEmptyDir("testIsTagEnabled");
254         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
255         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
256 
257         long before = System.currentTimeMillis();
258         dropbox.addText("DropBoxTest", "TEST-ENABLED");
259         assertTrue(dropbox.isTagEnabled("DropBoxTest"));
260 
261         ContentResolver cr = getContext().getContentResolver();
262         Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest",
263                                   "disabled");
264 
265         dropbox.addText("DropBoxTest", "TEST-DISABLED");
266         assertFalse(dropbox.isTagEnabled("DropBoxTest"));
267 
268         Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest",
269                                   "");
270 
271         dropbox.addText("DropBoxTest", "TEST-ENABLED-AGAIN");
272         assertTrue(dropbox.isTagEnabled("DropBoxTest"));
273 
274         DropBoxManager.Entry e0 = dropbox.getNextEntry("DropBoxTest", before);
275         DropBoxManager.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
276         assertTrue(null == dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis()));
277 
278         assertEquals("TEST-ENABLED", e0.getText(80));
279         assertEquals("TEST-ENABLED-AGAIN", e1.getText(80));
280 
281         e0.close();
282         e1.close();
283     }
284 
testGetNextEntry()285     public void testGetNextEntry() throws Exception {
286         File dir = getEmptyDir("testGetNextEntry");
287         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
288         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
289 
290         long before = System.currentTimeMillis();
291         dropbox.addText("DropBoxTest.A", "A0");
292         dropbox.addText("DropBoxTest.B", "B0");
293         dropbox.addText("DropBoxTest.A", "A1");
294 
295         DropBoxManager.Entry a0 = dropbox.getNextEntry("DropBoxTest.A", before);
296         DropBoxManager.Entry a1 = dropbox.getNextEntry("DropBoxTest.A", a0.getTimeMillis());
297         assertTrue(null == dropbox.getNextEntry("DropBoxTest.A", a1.getTimeMillis()));
298 
299         DropBoxManager.Entry b0 = dropbox.getNextEntry("DropBoxTest.B", before);
300         assertTrue(null == dropbox.getNextEntry("DropBoxTest.B", b0.getTimeMillis()));
301 
302         DropBoxManager.Entry x0 = dropbox.getNextEntry(null, before);
303         DropBoxManager.Entry x1 = dropbox.getNextEntry(null, x0.getTimeMillis());
304         DropBoxManager.Entry x2 = dropbox.getNextEntry(null, x1.getTimeMillis());
305         assertTrue(null == dropbox.getNextEntry(null, x2.getTimeMillis()));
306 
307         assertEquals("DropBoxTest.A", a0.getTag());
308         assertEquals("DropBoxTest.A", a1.getTag());
309         assertEquals("A0", a0.getText(80));
310         assertEquals("A1", a1.getText(80));
311 
312         assertEquals("DropBoxTest.B", b0.getTag());
313         assertEquals("B0", b0.getText(80));
314 
315         assertEquals("DropBoxTest.A", x0.getTag());
316         assertEquals("DropBoxTest.B", x1.getTag());
317         assertEquals("DropBoxTest.A", x2.getTag());
318         assertEquals("A0", x0.getText(80));
319         assertEquals("B0", x1.getText(80));
320         assertEquals("A1", x2.getText(80));
321 
322         a0.close();
323         a1.close();
324         b0.close();
325         x0.close();
326         x1.close();
327         x2.close();
328     }
329 
testSizeLimits()330     public void testSizeLimits() throws Exception {
331         File dir = getEmptyDir("testSizeLimits");
332         int blockSize =  new StatFs(dir.getPath()).getBlockSize();
333 
334         // Limit storage to 10 blocks
335         int kb = blockSize * 10 / 1024;
336         ContentResolver cr = getContext().getContentResolver();
337         Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, Integer.toString(kb));
338 
339         // Three tags using a total of 12 blocks:
340         // DropBoxTest0 [ ][ ]
341         // DropBoxTest1 [x][ ][    ][ ][xxx(20 blocks)xxx]
342         // DropBoxTest2 [xxxxxxxxxx][ ][ ]
343         //
344         // The blocks marked "x" will be removed due to storage restrictions.
345         // Use random fill (so it doesn't compress), subtract a little for gzip overhead
346 
347         final int overhead = 64;
348         long before = System.currentTimeMillis();
349         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
350         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
351 
352         addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
353         addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
354 
355         addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead);
356         addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead);
357         addRandomEntry(dropbox, "DropBoxTest1", blockSize * 2 - overhead);
358         addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead);
359         addRandomEntry(dropbox, "DropBoxTest1", blockSize * 20 - overhead);
360 
361         addRandomEntry(dropbox, "DropBoxTest2", blockSize * 4 - overhead);
362         addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead);
363         addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead);
364 
365         DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before);
366         DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
367         DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
368         DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
369         DropBoxManager.Entry e4 = dropbox.getNextEntry(null, e3.getTimeMillis());
370         DropBoxManager.Entry e5 = dropbox.getNextEntry(null, e4.getTimeMillis());
371         DropBoxManager.Entry e6 = dropbox.getNextEntry(null, e5.getTimeMillis());
372         DropBoxManager.Entry e7 = dropbox.getNextEntry(null, e6.getTimeMillis());
373         DropBoxManager.Entry e8 = dropbox.getNextEntry(null, e7.getTimeMillis());
374         DropBoxManager.Entry e9 = dropbox.getNextEntry(null, e8.getTimeMillis());
375         assertTrue(null == dropbox.getNextEntry(null, e9.getTimeMillis()));
376 
377         assertEquals("DropBoxTest0", e0.getTag());
378         assertEquals("DropBoxTest0", e1.getTag());
379         assertEquals(blockSize - overhead, getEntrySize(e0));
380         assertEquals(blockSize - overhead, getEntrySize(e1));
381 
382         assertEquals("DropBoxTest1", e2.getTag());
383         assertEquals("DropBoxTest1", e3.getTag());
384         assertEquals("DropBoxTest1", e4.getTag());
385         assertEquals("DropBoxTest1", e5.getTag());
386         assertEquals("DropBoxTest1", e6.getTag());
387         assertEquals(-1, getEntrySize(e2));  // Tombstone
388         assertEquals(blockSize - overhead, getEntrySize(e3));
389         assertEquals(blockSize * 2 - overhead, getEntrySize(e4));
390         assertEquals(blockSize - overhead, getEntrySize(e5));
391         assertEquals(-1, getEntrySize(e6));
392 
393         assertEquals("DropBoxTest2", e7.getTag());
394         assertEquals("DropBoxTest2", e8.getTag());
395         assertEquals("DropBoxTest2", e9.getTag());
396         assertEquals(-1, getEntrySize(e7));  // Tombstone
397         assertEquals(blockSize - overhead, getEntrySize(e8));
398         assertEquals(blockSize - overhead, getEntrySize(e9));
399 
400         e0.close();
401         e1.close();
402         e2.close();
403         e3.close();
404         e4.close();
405         e5.close();
406         e6.close();
407         e7.close();
408         e8.close();
409         e9.close();
410 
411         // Specifying a tag name skips tombstone records.
412 
413         DropBoxManager.Entry t0 = dropbox.getNextEntry("DropBoxTest1", before);
414         DropBoxManager.Entry t1 = dropbox.getNextEntry("DropBoxTest1", t0.getTimeMillis());
415         DropBoxManager.Entry t2 = dropbox.getNextEntry("DropBoxTest1", t1.getTimeMillis());
416         assertTrue(null == dropbox.getNextEntry("DropBoxTest1", t2.getTimeMillis()));
417 
418         assertEquals("DropBoxTest1", t0.getTag());
419         assertEquals("DropBoxTest1", t1.getTag());
420         assertEquals("DropBoxTest1", t2.getTag());
421 
422         assertEquals(blockSize - overhead, getEntrySize(t0));
423         assertEquals(blockSize * 2 - overhead, getEntrySize(t1));
424         assertEquals(blockSize - overhead, getEntrySize(t2));
425 
426         t0.close();
427         t1.close();
428         t2.close();
429     }
430 
testAgeLimits()431     public void testAgeLimits() throws Exception {
432         File dir = getEmptyDir("testAgeLimits");
433         int blockSize = new StatFs(dir.getPath()).getBlockSize();
434 
435         // Limit storage to 10 blocks with an expiration of 1 second
436         int kb = blockSize * 10 / 1024;
437         ContentResolver cr = getContext().getContentResolver();
438         Settings.Global.putString(cr, Settings.Global.DROPBOX_AGE_SECONDS, "1");
439         Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, Integer.toString(kb));
440 
441         // Write one normal entry and another so big that it is instantly tombstoned
442         long before = System.currentTimeMillis();
443         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
444         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
445 
446         dropbox.addText("DropBoxTest", "TEST");
447         addRandomEntry(dropbox, "DropBoxTest", blockSize * 20);
448 
449         // Verify that things are as expected
450         DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before);
451         DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
452         assertTrue(null == dropbox.getNextEntry(null, e1.getTimeMillis()));
453 
454         assertEquals("TEST", e0.getText(80));
455         assertEquals(null, e1.getText(80));
456         assertEquals(-1, getEntrySize(e1));
457 
458         e0.close();
459         e1.close();
460 
461         // Wait a second and write another entry -- old ones should be expunged
462         Thread.sleep(2000);
463         dropbox.addText("DropBoxTest", "TEST1");
464 
465         e0 = dropbox.getNextEntry(null, before);
466         assertTrue(null == dropbox.getNextEntry(null, e0.getTimeMillis()));
467         assertEquals("TEST1", e0.getText(80));
468         e0.close();
469     }
470 
testFileCountLimits()471     public void testFileCountLimits() throws Exception {
472         File dir = getEmptyDir("testFileCountLimits");
473 
474         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
475         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
476         dropbox.addText("DropBoxTest", "TEST0");
477         dropbox.addText("DropBoxTest", "TEST1");
478         dropbox.addText("DropBoxTest", "TEST2");
479         dropbox.addText("DropBoxTest", "TEST3");
480         dropbox.addText("DropBoxTest", "TEST4");
481         dropbox.addText("DropBoxTest", "TEST5");
482 
483         // Verify 6 files added
484         DropBoxManager.Entry e0 = dropbox.getNextEntry(null, 0);
485         DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
486         DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
487         DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
488         DropBoxManager.Entry e4 = dropbox.getNextEntry(null, e3.getTimeMillis());
489         DropBoxManager.Entry e5 = dropbox.getNextEntry(null, e4.getTimeMillis());
490         assertTrue(null == dropbox.getNextEntry(null, e5.getTimeMillis()));
491         assertEquals("TEST0", e0.getText(80));
492         assertEquals("TEST5", e5.getText(80));
493 
494         e0.close();
495         e1.close();
496         e2.close();
497         e3.close();
498         e4.close();
499         e5.close();
500 
501         // Limit to 3 files and add one more entry
502         ContentResolver cr = getContext().getContentResolver();
503         Settings.Global.putString(cr, Settings.Global.DROPBOX_MAX_FILES, "3");
504         dropbox.addText("DropBoxTest", "TEST6");
505 
506         // Verify only 3 files left
507         DropBoxManager.Entry f0 = dropbox.getNextEntry(null, 0);
508         DropBoxManager.Entry f1 = dropbox.getNextEntry(null, f0.getTimeMillis());
509         DropBoxManager.Entry f2 = dropbox.getNextEntry(null, f1.getTimeMillis());
510         assertTrue(null == dropbox.getNextEntry(null, f2.getTimeMillis()));
511         assertEquals("TEST4", f0.getText(80));
512         assertEquals("TEST5", f1.getText(80));
513         assertEquals("TEST6", f2.getText(80));
514 
515         f0.close();
516         f1.close();
517         f2.close();
518     }
519 
testCreateDropBoxManagerWithInvalidDirectory()520     public void testCreateDropBoxManagerWithInvalidDirectory() throws Exception {
521         // If created with an invalid directory, the DropBoxManager should suffer quietly
522         // and fail all operations (this is how it survives a full disk).
523         // Once the directory becomes possible to create, it will start working.
524 
525         File dir = new File(getEmptyDir("testCreateDropBoxManagerWith"), "InvalidDirectory");
526         new FileOutputStream(dir).close();  // Create an empty file
527         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
528         DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
529 
530         dropbox.addText("DropBoxTest", "should be ignored");
531         dropbox.addData("DropBoxTest", "should be ignored".getBytes(), 0);
532         assertTrue(null == dropbox.getNextEntry("DropBoxTest", 0));
533 
534         dir.delete();  // Remove the file so a directory can be created
535         dropbox.addText("DropBoxTest", "TEST");
536         DropBoxManager.Entry e = dropbox.getNextEntry("DropBoxTest", 0);
537         assertTrue(null == dropbox.getNextEntry("DropBoxTest", e.getTimeMillis()));
538         assertEquals("DropBoxTest", e.getTag());
539         assertEquals("TEST", e.getText(80));
540         e.close();
541     }
542 
testDropBoxEntrySerialization()543     public void testDropBoxEntrySerialization() throws Exception {
544         // Make sure DropBoxManager.Entry can be serialized to a Parcel and back
545         // under a variety of conditions.
546 
547         Parcel parcel = Parcel.obtain();
548         File dir = getEmptyDir("testDropBoxEntrySerialization");
549 
550         new DropBoxManager.Entry("empty", 1000000).writeToParcel(parcel, 0);
551         new DropBoxManager.Entry("string", 2000000, "String Value").writeToParcel(parcel, 0);
552         new DropBoxManager.Entry("bytes", 3000000, "Bytes Value".getBytes(),
553                 DropBoxManager.IS_TEXT).writeToParcel(parcel, 0);
554         new DropBoxManager.Entry("zerobytes", 4000000, new byte[0], 0).writeToParcel(parcel, 0);
555         new DropBoxManager.Entry("emptybytes", 5000000, (byte[]) null,
556                 DropBoxManager.IS_EMPTY).writeToParcel(parcel, 0);
557 
558         try {
559             new DropBoxManager.Entry("badbytes", 99999,
560                     "Bad Bytes Value".getBytes(),
561                     DropBoxManager.IS_EMPTY).writeToParcel(parcel, 0);
562             fail("IllegalArgumentException expected for non-null byte[] and IS_EMPTY flags");
563         } catch (IllegalArgumentException e) {
564             // expected
565         }
566 
567         try {
568             new DropBoxManager.Entry("badbytes", 99999, (byte[]) null, 0).writeToParcel(parcel, 0);
569             fail("IllegalArgumentException expected for null byte[] and non-IS_EMPTY flags");
570         } catch (IllegalArgumentException e) {
571             // expected
572         }
573 
574         File f = new File(dir, "file.dat");
575         FileOutputStream os = new FileOutputStream(f);
576         os.write("File Value".getBytes());
577         os.close();
578 
579         new DropBoxManager.Entry("file", 6000000, f, DropBoxManager.IS_TEXT).writeToParcel(
580                 parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
581         new DropBoxManager.Entry("binfile", 7000000, f, 0).writeToParcel(
582                 parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
583         new DropBoxManager.Entry("emptyfile", 8000000, (ParcelFileDescriptor) null,
584                 DropBoxManager.IS_EMPTY).writeToParcel(parcel, 0);
585 
586         try {
587             new DropBoxManager.Entry("badfile", 99999, new File(dir, "nonexist.dat"), 0);
588             fail("IOException expected for nonexistent file");
589         } catch (IOException e) {
590             // expected
591         }
592 
593         try {
594             new DropBoxManager.Entry("badfile", 99999, f, DropBoxManager.IS_EMPTY).writeToParcel(
595                     parcel, 0);
596             fail("IllegalArgumentException expected for non-null file and IS_EMPTY flags");
597         } catch (IllegalArgumentException e) {
598             // expected
599         }
600 
601         try {
602             new DropBoxManager.Entry("badfile", 99999, (ParcelFileDescriptor) null, 0);
603             fail("IllegalArgumentException expected for null PFD and non-IS_EMPTY flags");
604         } catch (IllegalArgumentException e) {
605             // expected
606         }
607 
608         File gz = new File(dir, "file.gz");
609         GZIPOutputStream gzout = new GZIPOutputStream(new FileOutputStream(gz));
610         gzout.write("Gzip File Value".getBytes());
611         gzout.close();
612 
613         new DropBoxManager.Entry("gzipfile", 9000000, gz,
614                 DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED).writeToParcel(
615                     parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
616         new DropBoxManager.Entry("gzipbinfile", 10000000, gz,
617                 DropBoxManager.IS_GZIPPED).writeToParcel(
618                     parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
619 
620         //
621         // Switch from writing to reading
622         //
623 
624         parcel.setDataPosition(0);
625         DropBoxManager.Entry e;
626 
627         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
628         assertEquals("empty", e.getTag());
629         assertEquals(1000000, e.getTimeMillis());
630         assertEquals(DropBoxManager.IS_EMPTY, e.getFlags());
631         assertEquals(null, e.getText(100));
632         assertEquals(null, e.getInputStream());
633         e.close();
634 
635         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
636         assertEquals("string", e.getTag());
637         assertEquals(2000000, e.getTimeMillis());
638         assertEquals(DropBoxManager.IS_TEXT, e.getFlags());
639         assertEquals("String Value", e.getText(100));
640         assertEquals("String Value",
641                 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine());
642         e.close();
643 
644         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
645         assertEquals("bytes", e.getTag());
646         assertEquals(3000000, e.getTimeMillis());
647         assertEquals(DropBoxManager.IS_TEXT, e.getFlags());
648         assertEquals("Bytes Value", e.getText(100));
649         e.close();
650 
651         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
652         assertEquals("zerobytes", e.getTag());
653         assertEquals(4000000, e.getTimeMillis());
654         assertEquals(0, e.getFlags());
655         assertEquals(null, e.getText(100));
656         assertEquals(null,
657                 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine());
658         e.close();
659 
660         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
661         assertEquals("emptybytes", e.getTag());
662         assertEquals(5000000, e.getTimeMillis());
663         assertEquals(DropBoxManager.IS_EMPTY, e.getFlags());
664         assertEquals(null, e.getText(100));
665         assertEquals(null, e.getInputStream());
666         e.close();
667 
668         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
669         assertEquals("file", e.getTag());
670         assertEquals(6000000, e.getTimeMillis());
671         assertEquals(DropBoxManager.IS_TEXT, e.getFlags());
672         assertEquals("File Value", e.getText(100));
673         e.close();
674 
675         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
676         assertEquals("binfile", e.getTag());
677         assertEquals(7000000, e.getTimeMillis());
678         assertEquals(0, e.getFlags());
679         assertEquals(null, e.getText(100));
680         assertEquals("File Value",
681                 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine());
682         e.close();
683         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
684         assertEquals("emptyfile", e.getTag());
685         assertEquals(8000000, e.getTimeMillis());
686         assertEquals(DropBoxManager.IS_EMPTY, e.getFlags());
687         assertEquals(null, e.getText(100));
688         assertEquals(null, e.getInputStream());
689         e.close();
690 
691         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
692         assertEquals("gzipfile", e.getTag());
693         assertEquals(9000000, e.getTimeMillis());
694         assertEquals(DropBoxManager.IS_TEXT, e.getFlags());
695         assertEquals("Gzip File Value", e.getText(100));
696         e.close();
697 
698         e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
699         assertEquals("gzipbinfile", e.getTag());
700         assertEquals(10000000, e.getTimeMillis());
701         assertEquals(0, e.getFlags());
702         assertEquals(null, e.getText(100));
703         assertEquals("Gzip File Value",
704                 new BufferedReader(new InputStreamReader(e.getInputStream())).readLine());
705         e.close();
706         assertEquals(0, parcel.dataAvail());
707         parcel.recycle();
708     }
709 
testDropBoxEntrySerializationDoesntLeakFileDescriptors()710     public void testDropBoxEntrySerializationDoesntLeakFileDescriptors() throws Exception {
711         File dir = getEmptyDir("testDropBoxEntrySerialization");
712         File f = new File(dir, "file.dat");
713         FileOutputStream os = new FileOutputStream(f);
714         os.write("File Value".getBytes());
715         os.close();
716 
717         int before = countOpenFiles();
718         assertTrue(before > 0);
719 
720         for (int i = 0; i < 1000; i++) {
721             Parcel parcel = Parcel.obtain();
722             new DropBoxManager.Entry("file", 1000000, f, 0).writeToParcel(
723                     parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
724 
725             parcel.setDataPosition(0);
726             DropBoxManager.Entry e = DropBoxManager.Entry.CREATOR.createFromParcel(parcel);
727             assertEquals("file", e.getTag());
728             e.close();
729 
730             parcel.recycle();
731         }
732 
733         int after = countOpenFiles();
734         assertTrue(after > 0);
735         assertTrue(after < before + 20);
736     }
737 
738     private void addRandomEntry(DropBoxManager dropbox, String tag, int size) throws Exception {
739         byte[] bytes = new byte[size];
740         new Random(System.currentTimeMillis()).nextBytes(bytes);
741 
742         File f = new File(getEmptyDir("addRandomEntry"), "random.dat");
743         FileOutputStream os = new FileOutputStream(f);
744         os.write(bytes);
745         os.close();
746 
747         dropbox.addFile(tag, f, 0);
748     }
749 
750     private int getEntrySize(DropBoxManager.Entry e) throws Exception {
751         InputStream is = e.getInputStream();
752         if (is == null) return -1;
753         int length = 0;
754         while (is.read() != -1) length++;
755         return length;
756     }
757 
758     private void recursiveDelete(File file) {
759         if (!file.delete() && file.isDirectory()) {
760             for (File f : file.listFiles()) recursiveDelete(f);
761             file.delete();
762         }
763     }
764 
765     private File getEmptyDir(String name) {
766         File dir = getContext().getDir("DropBoxTest." + name, 0);
767         for (File f : dir.listFiles()) recursiveDelete(f);
768         assertTrue(dir.listFiles().length == 0);
769         return dir;
770     }
771 
772     private int countOpenFiles() {
773         return new File("/proc/" + Process.myPid() + "/fd").listFiles().length;
774     }
775 }
776