• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.gallery3d.common;
18 
19 import com.android.gallery3d.common.BlobCache;
20 
21 import android.test.AndroidTestCase;
22 import android.test.suitebuilder.annotation.SmallTest;
23 import android.test.suitebuilder.annotation.MediumTest;
24 import android.test.suitebuilder.annotation.LargeTest;
25 import android.util.Log;
26 
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.RandomAccessFile;
30 import java.util.Random;
31 
32 public class BlobCacheTest extends AndroidTestCase {
33     private static final String TAG = "BlobCacheTest";
34 
35     @SmallTest
testReadIntLong()36     public void testReadIntLong() {
37         byte[] buf = new byte[9];
38         assertEquals(0, BlobCache.readInt(buf, 0));
39         assertEquals(0, BlobCache.readLong(buf, 0));
40         buf[0] = 1;
41         assertEquals(1, BlobCache.readInt(buf, 0));
42         assertEquals(1, BlobCache.readLong(buf, 0));
43         buf[3] = 0x7f;
44         assertEquals(0x7f000001, BlobCache.readInt(buf, 0));
45         assertEquals(0x7f000001, BlobCache.readLong(buf, 0));
46         assertEquals(0x007f0000, BlobCache.readInt(buf, 1));
47         assertEquals(0x007f0000, BlobCache.readLong(buf, 1));
48         buf[3] = (byte) 0x80;
49         buf[7] = (byte) 0xA0;
50         buf[0] = 0;
51         assertEquals(0x80000000, BlobCache.readInt(buf, 0));
52         assertEquals(0xA000000080000000L, BlobCache.readLong(buf, 0));
53         for (int i = 0; i < 8; i++) {
54             buf[i] = (byte) (0x11 * (i+8));
55         }
56         assertEquals(0xbbaa9988, BlobCache.readInt(buf, 0));
57         assertEquals(0xffeeddccbbaa9988L, BlobCache.readLong(buf, 0));
58         buf[8] = 0x33;
59         assertEquals(0x33ffeeddccbbaa99L, BlobCache.readLong(buf, 1));
60     }
61 
62     @SmallTest
testWriteIntLong()63     public void testWriteIntLong() {
64         byte[] buf = new byte[8];
65         BlobCache.writeInt(buf, 0, 0x12345678);
66         assertEquals(0x78, buf[0]);
67         assertEquals(0x56, buf[1]);
68         assertEquals(0x34, buf[2]);
69         assertEquals(0x12, buf[3]);
70         assertEquals(0x00, buf[4]);
71         BlobCache.writeLong(buf, 0, 0xffeeddccbbaa9988L);
72         for (int i = 0; i < 8; i++) {
73             assertEquals((byte) (0x11 * (i+8)), buf[i]);
74         }
75     }
76 
77     @MediumTest
testChecksum()78     public void testChecksum() throws IOException {
79         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
80         byte[] buf = new byte[0];
81         assertEquals(0x1, bc.checkSum(buf));
82         buf = new byte[1];
83         assertEquals(0x10001, bc.checkSum(buf));
84         buf[0] = 0x47;
85         assertEquals(0x480048, bc.checkSum(buf));
86         buf = new byte[3];
87         buf[0] = 0x10;
88         buf[1] = 0x30;
89         buf[2] = 0x01;
90         assertEquals(0x940042, bc.checkSum(buf));
91         assertEquals(0x310031, bc.checkSum(buf, 1, 1));
92         assertEquals(0x1, bc.checkSum(buf, 1, 0));
93         assertEquals(0x630032, bc.checkSum(buf, 1, 2));
94         buf = new byte[1024];
95         for (int i = 0; i < buf.length; i++) {
96             buf[i] = (byte)(i*i);
97         }
98         assertEquals(0x3574a610, bc.checkSum(buf));
99         bc.close();
100     }
101 
102     private static final int HEADER_SIZE = 32;
103     private static final int DATA_HEADER_SIZE = 4;
104     private static final int BLOB_HEADER_SIZE = 20;
105 
106     private static final String TEST_FILE_NAME = "/sdcard/btest";
107     private static final int MAX_ENTRIES = 100;
108     private static final int MAX_BYTES = 1000;
109     private static final int INDEX_SIZE = HEADER_SIZE + MAX_ENTRIES * 12 * 2;
110     private static final long KEY_0 = 0x1122334455667788L;
111     private static final long KEY_1 = 0x1122334455667789L;
112     private static final long KEY_2 = 0x112233445566778AL;
113     private static byte[] DATA_0 = new byte[10];
114     private static byte[] DATA_1 = new byte[10];
115 
116     @MediumTest
testBasic()117     public void testBasic() throws IOException {
118         String name = TEST_FILE_NAME;
119         BlobCache bc;
120         File idxFile = new File(name + ".idx");
121         File data0File = new File(name + ".0");
122         File data1File = new File(name + ".1");
123 
124         // Create a brand new cache.
125         bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, true);
126         bc.close();
127 
128         // Make sure the initial state is correct.
129         assertTrue(idxFile.exists());
130         assertTrue(data0File.exists());
131         assertTrue(data1File.exists());
132         assertEquals(INDEX_SIZE, idxFile.length());
133         assertEquals(DATA_HEADER_SIZE, data0File.length());
134         assertEquals(DATA_HEADER_SIZE, data1File.length());
135         assertEquals(0, bc.getActiveCount());
136 
137         // Re-open it.
138         bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
139         assertNull(bc.lookup(KEY_0));
140 
141         // insert one blob
142         genData(DATA_0, 1);
143         bc.insert(KEY_0, DATA_0);
144         assertSameData(DATA_0, bc.lookup(KEY_0));
145         assertEquals(1, bc.getActiveCount());
146         bc.close();
147 
148         // Make sure the file size is right.
149         assertEquals(INDEX_SIZE, idxFile.length());
150         assertEquals(DATA_HEADER_SIZE + BLOB_HEADER_SIZE + DATA_0.length,
151                 data0File.length());
152         assertEquals(DATA_HEADER_SIZE, data1File.length());
153 
154         // Re-open it and make sure we can get the old data
155         bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
156         assertSameData(DATA_0, bc.lookup(KEY_0));
157 
158         // insert with the same key (but using a different blob)
159         genData(DATA_0, 2);
160         bc.insert(KEY_0, DATA_0);
161         assertSameData(DATA_0, bc.lookup(KEY_0));
162         assertEquals(1, bc.getActiveCount());
163         bc.close();
164 
165         // Make sure the file size is right.
166         assertEquals(INDEX_SIZE, idxFile.length());
167         assertEquals(DATA_HEADER_SIZE + 2 * (BLOB_HEADER_SIZE + DATA_0.length),
168                 data0File.length());
169         assertEquals(DATA_HEADER_SIZE, data1File.length());
170 
171         // Re-open it and make sure we can get the old data
172         bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
173         assertSameData(DATA_0, bc.lookup(KEY_0));
174 
175         // insert another key and make sure we can get both key.
176         assertNull(bc.lookup(KEY_1));
177         genData(DATA_1, 3);
178         bc.insert(KEY_1, DATA_1);
179         assertSameData(DATA_0, bc.lookup(KEY_0));
180         assertSameData(DATA_1, bc.lookup(KEY_1));
181         assertEquals(2, bc.getActiveCount());
182         bc.close();
183 
184         // Make sure the file size is right.
185         assertEquals(INDEX_SIZE, idxFile.length());
186         assertEquals(DATA_HEADER_SIZE + 3 * (BLOB_HEADER_SIZE + DATA_0.length),
187                 data0File.length());
188         assertEquals(DATA_HEADER_SIZE, data1File.length());
189 
190         // Re-open it and make sure we can get the old data
191         bc = new BlobCache(name, 100, 1000, false);
192         assertSameData(DATA_0, bc.lookup(KEY_0));
193         assertSameData(DATA_1, bc.lookup(KEY_1));
194         assertEquals(2, bc.getActiveCount());
195         bc.close();
196     }
197 
198     @MediumTest
testNegativeKey()199     public void testNegativeKey() throws IOException {
200         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
201 
202         // insert one blob
203         genData(DATA_0, 1);
204         bc.insert(-123, DATA_0);
205         assertSameData(DATA_0, bc.lookup(-123));
206         bc.close();
207     }
208 
209     @MediumTest
testEmptyBlob()210     public void testEmptyBlob() throws IOException {
211         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
212 
213         byte[] data = new byte[0];
214         bc.insert(123, data);
215         assertSameData(data, bc.lookup(123));
216         bc.close();
217     }
218 
219     @MediumTest
testLookupRequest()220     public void testLookupRequest() throws IOException {
221         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
222 
223         // insert one blob
224         genData(DATA_0, 1);
225         bc.insert(1, DATA_0);
226         assertSameData(DATA_0, bc.lookup(1));
227 
228         // the same size buffer
229         byte[] buf = new byte[DATA_0.length];
230         BlobCache.LookupRequest req = new BlobCache.LookupRequest();
231         req.key = 1;
232         req.buffer = buf;
233         assertTrue(bc.lookup(req));
234         assertEquals(1, req.key);
235         assertSame(buf, req.buffer);
236         assertEquals(DATA_0.length, req.length);
237 
238         // larger buffer
239         buf = new byte[DATA_0.length + 22];
240         req = new BlobCache.LookupRequest();
241         req.key = 1;
242         req.buffer = buf;
243         assertTrue(bc.lookup(req));
244         assertEquals(1, req.key);
245         assertSame(buf, req.buffer);
246         assertEquals(DATA_0.length, req.length);
247 
248         // smaller buffer
249         buf = new byte[DATA_0.length - 1];
250         req = new BlobCache.LookupRequest();
251         req.key = 1;
252         req.buffer = buf;
253         assertTrue(bc.lookup(req));
254         assertEquals(1, req.key);
255         assertNotSame(buf, req.buffer);
256         assertEquals(DATA_0.length, req.length);
257         assertSameData(DATA_0, req.buffer, DATA_0.length);
258 
259         // null buffer
260         req = new BlobCache.LookupRequest();
261         req.key = 1;
262         req.buffer = null;
263         assertTrue(bc.lookup(req));
264         assertEquals(1, req.key);
265         assertNotNull(req.buffer);
266         assertEquals(DATA_0.length, req.length);
267         assertSameData(DATA_0, req.buffer, DATA_0.length);
268 
269         bc.close();
270     }
271 
272     @MediumTest
testKeyCollision()273     public void testKeyCollision() throws IOException {
274         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
275 
276         for (int i = 0; i < MAX_ENTRIES / 2; i++) {
277             genData(DATA_0, i);
278             long key = KEY_1 + i * MAX_ENTRIES;
279             bc.insert(key, DATA_0);
280         }
281 
282         for (int i = 0; i < MAX_ENTRIES / 2; i++) {
283             genData(DATA_0, i);
284             long key = KEY_1 + i * MAX_ENTRIES;
285             assertSameData(DATA_0, bc.lookup(key));
286         }
287         bc.close();
288     }
289 
290     @MediumTest
testRegionFlip()291     public void testRegionFlip() throws IOException {
292         String name = TEST_FILE_NAME;
293         BlobCache bc;
294         File idxFile = new File(name + ".idx");
295         File data0File = new File(name + ".0");
296         File data1File = new File(name + ".1");
297 
298         // Create a brand new cache.
299         bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, true);
300 
301         // This is the number of blobs fits into a region.
302         int maxFit = (MAX_BYTES - DATA_HEADER_SIZE) /
303                 (BLOB_HEADER_SIZE + DATA_0.length);
304 
305         for (int k = 0; k < maxFit; k++) {
306             genData(DATA_0, k);
307             bc.insert(k, DATA_0);
308         }
309         assertEquals(maxFit, bc.getActiveCount());
310 
311         // Make sure the file size is right.
312         assertEquals(INDEX_SIZE, idxFile.length());
313         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
314                 data0File.length());
315         assertEquals(DATA_HEADER_SIZE, data1File.length());
316 
317         // Now insert another one and let it flip.
318         genData(DATA_0, 777);
319         bc.insert(KEY_1, DATA_0);
320         assertEquals(1, bc.getActiveCount());
321 
322         assertEquals(INDEX_SIZE, idxFile.length());
323         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
324                 data0File.length());
325         assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
326                 data1File.length());
327 
328         // Make sure we can find the new data
329         assertSameData(DATA_0, bc.lookup(KEY_1));
330 
331         // Now find an old blob
332         int old = maxFit / 2;
333         genData(DATA_0, old);
334         assertSameData(DATA_0, bc.lookup(old));
335         assertEquals(2, bc.getActiveCount());
336 
337         // Observed data is copied.
338         assertEquals(INDEX_SIZE, idxFile.length());
339         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
340                 data0File.length());
341         assertEquals(DATA_HEADER_SIZE + 2 * (BLOB_HEADER_SIZE + DATA_0.length),
342                 data1File.length());
343 
344         // Now copy everything over (except we should have no space for the last one)
345         assertTrue(old < maxFit - 1);
346         for (int k = 0; k < maxFit; k++) {
347             genData(DATA_0, k);
348             assertSameData(DATA_0, bc.lookup(k));
349         }
350         assertEquals(maxFit, bc.getActiveCount());
351 
352         // Now both file should be full.
353         assertEquals(INDEX_SIZE, idxFile.length());
354         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
355                 data0File.length());
356         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
357                 data1File.length());
358 
359         // Now insert one to make it flip.
360         genData(DATA_0, 888);
361         bc.insert(KEY_2, DATA_0);
362         assertEquals(1, bc.getActiveCount());
363 
364         // Check the size after the second flip.
365         assertEquals(INDEX_SIZE, idxFile.length());
366         assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
367                 data0File.length());
368         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
369                 data1File.length());
370 
371         // Now the last key should be gone.
372         assertNull(bc.lookup(maxFit - 1));
373 
374         // But others should remain
375         for (int k = 0; k < maxFit - 1; k++) {
376             genData(DATA_0, k);
377             assertSameData(DATA_0, bc.lookup(k));
378         }
379 
380         assertEquals(maxFit, bc.getActiveCount());
381         genData(DATA_0, 777);
382         assertSameData(DATA_0, bc.lookup(KEY_1));
383         genData(DATA_0, 888);
384         assertSameData(DATA_0, bc.lookup(KEY_2));
385         assertEquals(maxFit, bc.getActiveCount());
386 
387         // Now two files should be full.
388         assertEquals(INDEX_SIZE, idxFile.length());
389         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
390                 data0File.length());
391         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
392                 data1File.length());
393 
394         bc.close();
395     }
396 
397     @MediumTest
398     public void testEntryLimit() throws IOException {
399         String name = TEST_FILE_NAME;
400         BlobCache bc;
401         File idxFile = new File(name + ".idx");
402         File data0File = new File(name + ".0");
403         File data1File = new File(name + ".1");
404         int maxEntries = 10;
405         int maxFit = maxEntries / 2;
406         int indexSize = HEADER_SIZE + maxEntries * 12 * 2;
407 
408         // Create a brand new cache with a small entry limit.
409         bc = new BlobCache(name, maxEntries, MAX_BYTES, true);
410 
411         // Fill to just before flipping
412         for (int i = 0; i < maxFit; i++) {
413             genData(DATA_0, i);
414             bc.insert(i, DATA_0);
415         }
416         assertEquals(maxFit, bc.getActiveCount());
417 
418         // Check the file size.
419         assertEquals(indexSize, idxFile.length());
420         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
421                 data0File.length());
422         assertEquals(DATA_HEADER_SIZE, data1File.length());
423 
424         // Insert one and make it flip
425         genData(DATA_0, 777);
426         bc.insert(777, DATA_0);
427         assertEquals(1, bc.getActiveCount());
428 
429         // Check the file size.
430         assertEquals(indexSize, idxFile.length());
431         assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
432                 data0File.length());
433         assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
434                 data1File.length());
435         bc.close();
436     }
437 
438     @LargeTest
439     public void testDataIntegrity() throws IOException {
440         String name = TEST_FILE_NAME;
441         File idxFile = new File(name + ".idx");
442         File data0File = new File(name + ".0");
443         File data1File = new File(name + ".1");
444         RandomAccessFile f;
445 
446         Log.v(TAG, "It should be readable if the content is not changed.");
447         prepareNewCache();
448         f = new RandomAccessFile(data0File, "rw");
449         f.seek(1);
450         byte b = f.readByte();
451         f.seek(1);
452         f.write(b);
453         f.close();
454         assertReadable();
455 
456         Log.v(TAG, "Change the data file magic field");
457         prepareNewCache();
458         f = new RandomAccessFile(data0File, "rw");
459         f.seek(1);
460         f.write(0xFF);
461         f.close();
462         assertUnreadable();
463 
464         prepareNewCache();
465         f = new RandomAccessFile(data1File, "rw");
466         f.write(0xFF);
467         f.close();
468         assertUnreadable();
469 
470         Log.v(TAG, "Change the blob key");
471         prepareNewCache();
472         f = new RandomAccessFile(data0File, "rw");
473         f.seek(4);
474         f.write(0x00);
475         f.close();
476         assertUnreadable();
477 
478         Log.v(TAG, "Change the blob checksum");
479         prepareNewCache();
480         f = new RandomAccessFile(data0File, "rw");
481         f.seek(4 + 8);
482         f.write(0x00);
483         f.close();
484         assertUnreadable();
485 
486         Log.v(TAG, "Change the blob offset");
487         prepareNewCache();
488         f = new RandomAccessFile(data0File, "rw");
489         f.seek(4 + 12);
490         f.write(0x20);
491         f.close();
492         assertUnreadable();
493 
494         Log.v(TAG, "Change the blob length: some other value");
495         prepareNewCache();
496         f = new RandomAccessFile(data0File, "rw");
497         f.seek(4 + 16);
498         f.write(0x20);
499         f.close();
500         assertUnreadable();
501 
502         Log.v(TAG, "Change the blob length: -1");
503         prepareNewCache();
504         f = new RandomAccessFile(data0File, "rw");
505         f.seek(4 + 16);
506         f.writeInt(0xFFFFFFFF);
507         f.close();
508         assertUnreadable();
509 
510         Log.v(TAG, "Change the blob length: big value");
511         prepareNewCache();
512         f = new RandomAccessFile(data0File, "rw");
513         f.seek(4 + 16);
514         f.writeInt(0xFFFFFF00);
515         f.close();
516         assertUnreadable();
517 
518         Log.v(TAG, "Change the blob content");
519         prepareNewCache();
520         f = new RandomAccessFile(data0File, "rw");
521         f.seek(4 + 20);
522         f.write(0x01);
523         f.close();
524         assertUnreadable();
525 
526         Log.v(TAG, "Change the index magic");
527         prepareNewCache();
528         f = new RandomAccessFile(idxFile, "rw");
529         f.seek(1);
530         f.write(0x00);
531         f.close();
532         assertUnreadable();
533 
534         Log.v(TAG, "Change the active region");
535         prepareNewCache();
536         f = new RandomAccessFile(idxFile, "rw");
537         f.seek(12);
538         f.write(0x01);
539         f.close();
540         assertUnreadable();
541 
542         Log.v(TAG, "Change the reserved data");
543         prepareNewCache();
544         f = new RandomAccessFile(idxFile, "rw");
545         f.seek(24);
546         f.write(0x01);
547         f.close();
548         assertUnreadable();
549 
550         Log.v(TAG, "Change the checksum");
551         prepareNewCache();
552         f = new RandomAccessFile(idxFile, "rw");
553         f.seek(29);
554         f.write(0x00);
555         f.close();
556         assertUnreadable();
557 
558         Log.v(TAG, "Change the key");
559         prepareNewCache();
560         f = new RandomAccessFile(idxFile, "rw");
561         f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES));
562         f.write(0x00);
563         f.close();
564         assertUnreadable();
565 
566         Log.v(TAG, "Change the offset");
567         prepareNewCache();
568         f = new RandomAccessFile(idxFile, "rw");
569         f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES) + 8);
570         f.write(0x05);
571         f.close();
572         assertUnreadable();
573 
574         Log.v(TAG, "Change the offset");
575         prepareNewCache();
576         f = new RandomAccessFile(idxFile, "rw");
577         f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES) + 8 + 3);
578         f.write(0xFF);
579         f.close();
580         assertUnreadable();
581 
582         Log.v(TAG, "Garbage index");
583         prepareNewCache();
584         f = new RandomAccessFile(idxFile, "rw");
585         int n = (int) idxFile.length();
586         f.seek(32);
587         byte[] garbage = new byte[1024];
588         for (int i = 0; i < garbage.length; i++) {
589             garbage[i] = (byte) 0x80;
590         }
591         int i = 32;
592         while (i < n) {
593             int todo = Math.min(garbage.length, n - i);
594             f.write(garbage, 0, todo);
595             i += todo;
596         }
597         f.close();
598         assertUnreadable();
599     }
600 
601     // Create a brand new cache and put one entry into it.
602     private void prepareNewCache() throws IOException {
603         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
604         genData(DATA_0, 777);
605         bc.insert(KEY_1, DATA_0);
606         bc.close();
607     }
608 
609     private void assertReadable() throws IOException {
610         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, false);
611         genData(DATA_0, 777);
612         assertSameData(DATA_0, bc.lookup(KEY_1));
613         bc.close();
614     }
615 
616     private void assertUnreadable() throws IOException {
617         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, false);
618         genData(DATA_0, 777);
619         assertNull(bc.lookup(KEY_1));
620         bc.close();
621     }
622 
623     @LargeTest
624     public void testRandomSize() throws IOException {
625         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
626 
627         // Random size test
628         Random rand = new Random(0);
629         for (int i = 0; i < 100; i++) {
630             byte[] data = new byte[rand.nextInt(MAX_BYTES*12/10)];
631             try {
632                 bc.insert(rand.nextLong(), data);
633                 if (data.length > MAX_BYTES - 4 - 20) fail();
634             } catch (RuntimeException ex) {
635                 if (data.length <= MAX_BYTES - 4 - 20) fail();
636             }
637         }
638 
639         bc.close();
640     }
641 
642     @LargeTest
643     public void testBandwidth() throws IOException {
644         BlobCache bc = new BlobCache(TEST_FILE_NAME, 1000, 10000000, true);
645 
646         // Write
647         int count = 0;
648         byte[] data = new byte[20000];
649         long t0 = System.nanoTime();
650         for (int i = 0; i < 1000; i++) {
651             bc.insert(i, data);
652             count += data.length;
653         }
654         bc.syncAll();
655         float delta = (System.nanoTime() - t0) * 1e-3f;
656         Log.v(TAG, "write bandwidth = " + (count / delta) + " M/s");
657 
658         // Copy over
659         BlobCache.LookupRequest req = new BlobCache.LookupRequest();
660         count = 0;
661         t0 = System.nanoTime();
662         for (int i = 0; i < 1000; i++) {
663             req.key = i;
664             req.buffer = data;
665             if (bc.lookup(req)) {
666                 count += req.length;
667             }
668         }
669         bc.syncAll();
670         delta = (System.nanoTime() - t0) * 1e-3f;
671         Log.v(TAG, "copy over bandwidth = " + (count / delta) + " M/s");
672 
673         // Read
674         count = 0;
675         t0 = System.nanoTime();
676         for (int i = 0; i < 1000; i++) {
677             req.key = i;
678             req.buffer = data;
679             if (bc.lookup(req)) {
680                 count += req.length;
681             }
682         }
683         bc.syncAll();
684         delta = (System.nanoTime() - t0) * 1e-3f;
685         Log.v(TAG, "read bandwidth = " + (count / delta) + " M/s");
686 
687         bc.close();
688     }
689 
690     @LargeTest
691     public void testSmallSize() throws IOException {
692         BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, 40, true);
693 
694         // Small size test
695         Random rand = new Random(0);
696         for (int i = 0; i < 100; i++) {
697             byte[] data = new byte[rand.nextInt(3)];
698             bc.insert(rand.nextLong(), data);
699         }
700 
701         bc.close();
702     }
703 
704     @LargeTest
705     public void testManyEntries() throws IOException {
706         BlobCache bc = new BlobCache(TEST_FILE_NAME, 1, MAX_BYTES, true);
707 
708         // Many entries test
709         Random rand = new Random(0);
710         for (int i = 0; i < 100; i++) {
711             byte[] data = new byte[rand.nextInt(10)];
712         }
713 
714         bc.close();
715     }
716 
717     private void genData(byte[] data, int seed) {
718         for(int i = 0; i < data.length; i++) {
719             data[i] = (byte) (seed * i);
720         }
721     }
722 
723     private void assertSameData(byte[] data1, byte[] data2) {
724         if (data1 == null && data2 == null) return;
725         if (data1 == null || data2 == null) fail();
726         if (data1.length != data2.length) fail();
727         for (int i = 0; i < data1.length; i++) {
728             if (data1[i] != data2[i]) fail();
729         }
730     }
731 
732     private void assertSameData(byte[] data1, byte[] data2, int n) {
733         if (data1 == null || data2 == null) fail();
734         for (int i = 0; i < n; i++) {
735             if (data1[i] != data2[i]) fail();
736         }
737     }
738 }
739