Home | History | Annotate | Download | only in common
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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