/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.gallery3d.common;

import com.android.gallery3d.common.BlobCache;

import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Random;

public class BlobCacheTest extends AndroidTestCase {
    private static final String TAG = "BlobCacheTest";

    @SmallTest
    public void testReadIntLong() {
        byte[] buf = new byte[9];
        assertEquals(0, BlobCache.readInt(buf, 0));
        assertEquals(0, BlobCache.readLong(buf, 0));
        buf[0] = 1;
        assertEquals(1, BlobCache.readInt(buf, 0));
        assertEquals(1, BlobCache.readLong(buf, 0));
        buf[3] = 0x7f;
        assertEquals(0x7f000001, BlobCache.readInt(buf, 0));
        assertEquals(0x7f000001, BlobCache.readLong(buf, 0));
        assertEquals(0x007f0000, BlobCache.readInt(buf, 1));
        assertEquals(0x007f0000, BlobCache.readLong(buf, 1));
        buf[3] = (byte) 0x80;
        buf[7] = (byte) 0xA0;
        buf[0] = 0;
        assertEquals(0x80000000, BlobCache.readInt(buf, 0));
        assertEquals(0xA000000080000000L, BlobCache.readLong(buf, 0));
        for (int i = 0; i < 8; i++) {
            buf[i] = (byte) (0x11 * (i+8));
        }
        assertEquals(0xbbaa9988, BlobCache.readInt(buf, 0));
        assertEquals(0xffeeddccbbaa9988L, BlobCache.readLong(buf, 0));
        buf[8] = 0x33;
        assertEquals(0x33ffeeddccbbaa99L, BlobCache.readLong(buf, 1));
    }

    @SmallTest
    public void testWriteIntLong() {
        byte[] buf = new byte[8];
        BlobCache.writeInt(buf, 0, 0x12345678);
        assertEquals(0x78, buf[0]);
        assertEquals(0x56, buf[1]);
        assertEquals(0x34, buf[2]);
        assertEquals(0x12, buf[3]);
        assertEquals(0x00, buf[4]);
        BlobCache.writeLong(buf, 0, 0xffeeddccbbaa9988L);
        for (int i = 0; i < 8; i++) {
            assertEquals((byte) (0x11 * (i+8)), buf[i]);
        }
    }

    @MediumTest
    public void testChecksum() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
        byte[] buf = new byte[0];
        assertEquals(0x1, bc.checkSum(buf));
        buf = new byte[1];
        assertEquals(0x10001, bc.checkSum(buf));
        buf[0] = 0x47;
        assertEquals(0x480048, bc.checkSum(buf));
        buf = new byte[3];
        buf[0] = 0x10;
        buf[1] = 0x30;
        buf[2] = 0x01;
        assertEquals(0x940042, bc.checkSum(buf));
        assertEquals(0x310031, bc.checkSum(buf, 1, 1));
        assertEquals(0x1, bc.checkSum(buf, 1, 0));
        assertEquals(0x630032, bc.checkSum(buf, 1, 2));
        buf = new byte[1024];
        for (int i = 0; i < buf.length; i++) {
            buf[i] = (byte)(i*i);
        }
        assertEquals(0x3574a610, bc.checkSum(buf));
        bc.close();
    }

    private static final int HEADER_SIZE = 32;
    private static final int DATA_HEADER_SIZE = 4;
    private static final int BLOB_HEADER_SIZE = 20;

    private static final String TEST_FILE_NAME = "/sdcard/btest";
    private static final int MAX_ENTRIES = 100;
    private static final int MAX_BYTES = 1000;
    private static final int INDEX_SIZE = HEADER_SIZE + MAX_ENTRIES * 12 * 2;
    private static final long KEY_0 = 0x1122334455667788L;
    private static final long KEY_1 = 0x1122334455667789L;
    private static final long KEY_2 = 0x112233445566778AL;
    private static byte[] DATA_0 = new byte[10];
    private static byte[] DATA_1 = new byte[10];

    @MediumTest
    public void testBasic() throws IOException {
        String name = TEST_FILE_NAME;
        BlobCache bc;
        File idxFile = new File(name + ".idx");
        File data0File = new File(name + ".0");
        File data1File = new File(name + ".1");

        // Create a brand new cache.
        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, true);
        bc.close();

        // Make sure the initial state is correct.
        assertTrue(idxFile.exists());
        assertTrue(data0File.exists());
        assertTrue(data1File.exists());
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE, data0File.length());
        assertEquals(DATA_HEADER_SIZE, data1File.length());
        assertEquals(0, bc.getActiveCount());

        // Re-open it.
        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
        assertNull(bc.lookup(KEY_0));

        // insert one blob
        genData(DATA_0, 1);
        bc.insert(KEY_0, DATA_0);
        assertSameData(DATA_0, bc.lookup(KEY_0));
        assertEquals(1, bc.getActiveCount());
        bc.close();

        // Make sure the file size is right.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + BLOB_HEADER_SIZE + DATA_0.length,
                data0File.length());
        assertEquals(DATA_HEADER_SIZE, data1File.length());

        // Re-open it and make sure we can get the old data
        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
        assertSameData(DATA_0, bc.lookup(KEY_0));

        // insert with the same key (but using a different blob)
        genData(DATA_0, 2);
        bc.insert(KEY_0, DATA_0);
        assertSameData(DATA_0, bc.lookup(KEY_0));
        assertEquals(1, bc.getActiveCount());
        bc.close();

        // Make sure the file size is right.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + 2 * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE, data1File.length());

        // Re-open it and make sure we can get the old data
        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, false);
        assertSameData(DATA_0, bc.lookup(KEY_0));

        // insert another key and make sure we can get both key.
        assertNull(bc.lookup(KEY_1));
        genData(DATA_1, 3);
        bc.insert(KEY_1, DATA_1);
        assertSameData(DATA_0, bc.lookup(KEY_0));
        assertSameData(DATA_1, bc.lookup(KEY_1));
        assertEquals(2, bc.getActiveCount());
        bc.close();

        // Make sure the file size is right.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + 3 * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE, data1File.length());

        // Re-open it and make sure we can get the old data
        bc = new BlobCache(name, 100, 1000, false);
        assertSameData(DATA_0, bc.lookup(KEY_0));
        assertSameData(DATA_1, bc.lookup(KEY_1));
        assertEquals(2, bc.getActiveCount());
        bc.close();
    }

    @MediumTest
    public void testNegativeKey() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);

        // insert one blob
        genData(DATA_0, 1);
        bc.insert(-123, DATA_0);
        assertSameData(DATA_0, bc.lookup(-123));
        bc.close();
    }

    @MediumTest
    public void testEmptyBlob() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);

        byte[] data = new byte[0];
        bc.insert(123, data);
        assertSameData(data, bc.lookup(123));
        bc.close();
    }

    @MediumTest
    public void testLookupRequest() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);

        // insert one blob
        genData(DATA_0, 1);
        bc.insert(1, DATA_0);
        assertSameData(DATA_0, bc.lookup(1));

        // the same size buffer
        byte[] buf = new byte[DATA_0.length];
        BlobCache.LookupRequest req = new BlobCache.LookupRequest();
        req.key = 1;
        req.buffer = buf;
        assertTrue(bc.lookup(req));
        assertEquals(1, req.key);
        assertSame(buf, req.buffer);
        assertEquals(DATA_0.length, req.length);

        // larger buffer
        buf = new byte[DATA_0.length + 22];
        req = new BlobCache.LookupRequest();
        req.key = 1;
        req.buffer = buf;
        assertTrue(bc.lookup(req));
        assertEquals(1, req.key);
        assertSame(buf, req.buffer);
        assertEquals(DATA_0.length, req.length);

        // smaller buffer
        buf = new byte[DATA_0.length - 1];
        req = new BlobCache.LookupRequest();
        req.key = 1;
        req.buffer = buf;
        assertTrue(bc.lookup(req));
        assertEquals(1, req.key);
        assertNotSame(buf, req.buffer);
        assertEquals(DATA_0.length, req.length);
        assertSameData(DATA_0, req.buffer, DATA_0.length);

        // null buffer
        req = new BlobCache.LookupRequest();
        req.key = 1;
        req.buffer = null;
        assertTrue(bc.lookup(req));
        assertEquals(1, req.key);
        assertNotNull(req.buffer);
        assertEquals(DATA_0.length, req.length);
        assertSameData(DATA_0, req.buffer, DATA_0.length);

        bc.close();
    }

    @MediumTest
    public void testKeyCollision() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);

        for (int i = 0; i < MAX_ENTRIES / 2; i++) {
            genData(DATA_0, i);
            long key = KEY_1 + i * MAX_ENTRIES;
            bc.insert(key, DATA_0);
        }

        for (int i = 0; i < MAX_ENTRIES / 2; i++) {
            genData(DATA_0, i);
            long key = KEY_1 + i * MAX_ENTRIES;
            assertSameData(DATA_0, bc.lookup(key));
        }
        bc.close();
    }

    @MediumTest
    public void testRegionFlip() throws IOException {
        String name = TEST_FILE_NAME;
        BlobCache bc;
        File idxFile = new File(name + ".idx");
        File data0File = new File(name + ".0");
        File data1File = new File(name + ".1");

        // Create a brand new cache.
        bc = new BlobCache(name, MAX_ENTRIES, MAX_BYTES, true);

        // This is the number of blobs fits into a region.
        int maxFit = (MAX_BYTES - DATA_HEADER_SIZE) /
                (BLOB_HEADER_SIZE + DATA_0.length);

        for (int k = 0; k < maxFit; k++) {
            genData(DATA_0, k);
            bc.insert(k, DATA_0);
        }
        assertEquals(maxFit, bc.getActiveCount());

        // Make sure the file size is right.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE, data1File.length());

        // Now insert another one and let it flip.
        genData(DATA_0, 777);
        bc.insert(KEY_1, DATA_0);
        assertEquals(1, bc.getActiveCount());

        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
                data1File.length());

        // Make sure we can find the new data
        assertSameData(DATA_0, bc.lookup(KEY_1));

        // Now find an old blob
        int old = maxFit / 2;
        genData(DATA_0, old);
        assertSameData(DATA_0, bc.lookup(old));
        assertEquals(2, bc.getActiveCount());

        // Observed data is copied.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE + 2 * (BLOB_HEADER_SIZE + DATA_0.length),
                data1File.length());

        // Now copy everything over (except we should have no space for the last one)
        assertTrue(old < maxFit - 1);
        for (int k = 0; k < maxFit; k++) {
            genData(DATA_0, k);
            assertSameData(DATA_0, bc.lookup(k));
        }
        assertEquals(maxFit, bc.getActiveCount());

        // Now both file should be full.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data1File.length());

        // Now insert one to make it flip.
        genData(DATA_0, 888);
        bc.insert(KEY_2, DATA_0);
        assertEquals(1, bc.getActiveCount());

        // Check the size after the second flip.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data1File.length());

        // Now the last key should be gone.
        assertNull(bc.lookup(maxFit - 1));

        // But others should remain
        for (int k = 0; k < maxFit - 1; k++) {
            genData(DATA_0, k);
            assertSameData(DATA_0, bc.lookup(k));
        }

        assertEquals(maxFit, bc.getActiveCount());
        genData(DATA_0, 777);
        assertSameData(DATA_0, bc.lookup(KEY_1));
        genData(DATA_0, 888);
        assertSameData(DATA_0, bc.lookup(KEY_2));
        assertEquals(maxFit, bc.getActiveCount());

        // Now two files should be full.
        assertEquals(INDEX_SIZE, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data1File.length());

        bc.close();
    }

    @MediumTest
    public void testEntryLimit() throws IOException {
        String name = TEST_FILE_NAME;
        BlobCache bc;
        File idxFile = new File(name + ".idx");
        File data0File = new File(name + ".0");
        File data1File = new File(name + ".1");
        int maxEntries = 10;
        int maxFit = maxEntries / 2;
        int indexSize = HEADER_SIZE + maxEntries * 12 * 2;

        // Create a brand new cache with a small entry limit.
        bc = new BlobCache(name, maxEntries, MAX_BYTES, true);

        // Fill to just before flipping
        for (int i = 0; i < maxFit; i++) {
            genData(DATA_0, i);
            bc.insert(i, DATA_0);
        }
        assertEquals(maxFit, bc.getActiveCount());

        // Check the file size.
        assertEquals(indexSize, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE, data1File.length());

        // Insert one and make it flip
        genData(DATA_0, 777);
        bc.insert(777, DATA_0);
        assertEquals(1, bc.getActiveCount());

        // Check the file size.
        assertEquals(indexSize, idxFile.length());
        assertEquals(DATA_HEADER_SIZE + maxFit * (BLOB_HEADER_SIZE + DATA_0.length),
                data0File.length());
        assertEquals(DATA_HEADER_SIZE + 1 * (BLOB_HEADER_SIZE + DATA_0.length),
                data1File.length());
        bc.close();
    }

    @LargeTest
    public void testDataIntegrity() throws IOException {
        String name = TEST_FILE_NAME;
        File idxFile = new File(name + ".idx");
        File data0File = new File(name + ".0");
        File data1File = new File(name + ".1");
        RandomAccessFile f;

        Log.v(TAG, "It should be readable if the content is not changed.");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(1);
        byte b = f.readByte();
        f.seek(1);
        f.write(b);
        f.close();
        assertReadable();

        Log.v(TAG, "Change the data file magic field");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(1);
        f.write(0xFF);
        f.close();
        assertUnreadable();

        prepareNewCache();
        f = new RandomAccessFile(data1File, "rw");
        f.write(0xFF);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the blob key");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(4);
        f.write(0x00);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the blob checksum");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(4 + 8);
        f.write(0x00);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the blob offset");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(4 + 12);
        f.write(0x20);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the blob length: some other value");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(4 + 16);
        f.write(0x20);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the blob length: -1");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(4 + 16);
        f.writeInt(0xFFFFFFFF);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the blob length: big value");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(4 + 16);
        f.writeInt(0xFFFFFF00);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the blob content");
        prepareNewCache();
        f = new RandomAccessFile(data0File, "rw");
        f.seek(4 + 20);
        f.write(0x01);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the index magic");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        f.seek(1);
        f.write(0x00);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the active region");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        f.seek(12);
        f.write(0x01);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the reserved data");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        f.seek(24);
        f.write(0x01);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the checksum");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        f.seek(29);
        f.write(0x00);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the key");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES));
        f.write(0x00);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the offset");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES) + 8);
        f.write(0x05);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Change the offset");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        f.seek(32 + 12 * (KEY_1 % MAX_ENTRIES) + 8 + 3);
        f.write(0xFF);
        f.close();
        assertUnreadable();

        Log.v(TAG, "Garbage index");
        prepareNewCache();
        f = new RandomAccessFile(idxFile, "rw");
        int n = (int) idxFile.length();
        f.seek(32);
        byte[] garbage = new byte[1024];
        for (int i = 0; i < garbage.length; i++) {
            garbage[i] = (byte) 0x80;
        }
        int i = 32;
        while (i < n) {
            int todo = Math.min(garbage.length, n - i);
            f.write(garbage, 0, todo);
            i += todo;
        }
        f.close();
        assertUnreadable();
    }

    // Create a brand new cache and put one entry into it.
    private void prepareNewCache() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);
        genData(DATA_0, 777);
        bc.insert(KEY_1, DATA_0);
        bc.close();
    }

    private void assertReadable() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, false);
        genData(DATA_0, 777);
        assertSameData(DATA_0, bc.lookup(KEY_1));
        bc.close();
    }

    private void assertUnreadable() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, false);
        genData(DATA_0, 777);
        assertNull(bc.lookup(KEY_1));
        bc.close();
    }

    @LargeTest
    public void testRandomSize() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, MAX_BYTES, true);

        // Random size test
        Random rand = new Random(0);
        for (int i = 0; i < 100; i++) {
            byte[] data = new byte[rand.nextInt(MAX_BYTES*12/10)];
            try {
                bc.insert(rand.nextLong(), data);
                if (data.length > MAX_BYTES - 4 - 20) fail();
            } catch (RuntimeException ex) {
                if (data.length <= MAX_BYTES - 4 - 20) fail();
            }
        }

        bc.close();
    }

    @LargeTest
    public void testBandwidth() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, 1000, 10000000, true);

        // Write
        int count = 0;
        byte[] data = new byte[20000];
        long t0 = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            bc.insert(i, data);
            count += data.length;
        }
        bc.syncAll();
        float delta = (System.nanoTime() - t0) * 1e-3f;
        Log.v(TAG, "write bandwidth = " + (count / delta) + " M/s");

        // Copy over
        BlobCache.LookupRequest req = new BlobCache.LookupRequest();
        count = 0;
        t0 = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            req.key = i;
            req.buffer = data;
            if (bc.lookup(req)) {
                count += req.length;
            }
        }
        bc.syncAll();
        delta = (System.nanoTime() - t0) * 1e-3f;
        Log.v(TAG, "copy over bandwidth = " + (count / delta) + " M/s");

        // Read
        count = 0;
        t0 = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            req.key = i;
            req.buffer = data;
            if (bc.lookup(req)) {
                count += req.length;
            }
        }
        bc.syncAll();
        delta = (System.nanoTime() - t0) * 1e-3f;
        Log.v(TAG, "read bandwidth = " + (count / delta) + " M/s");

        bc.close();
    }

    @LargeTest
    public void testSmallSize() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, MAX_ENTRIES, 40, true);

        // Small size test
        Random rand = new Random(0);
        for (int i = 0; i < 100; i++) {
            byte[] data = new byte[rand.nextInt(3)];
            bc.insert(rand.nextLong(), data);
        }

        bc.close();
    }

    @LargeTest
    public void testManyEntries() throws IOException {
        BlobCache bc = new BlobCache(TEST_FILE_NAME, 1, MAX_BYTES, true);

        // Many entries test
        Random rand = new Random(0);
        for (int i = 0; i < 100; i++) {
            byte[] data = new byte[rand.nextInt(10)];
        }

        bc.close();
    }

    private void genData(byte[] data, int seed) {
        for(int i = 0; i < data.length; i++) {
            data[i] = (byte) (seed * i);
        }
    }

    private void assertSameData(byte[] data1, byte[] data2) {
        if (data1 == null && data2 == null) return;
        if (data1 == null || data2 == null) fail();
        if (data1.length != data2.length) fail();
        for (int i = 0; i < data1.length; i++) {
            if (data1[i] != data2[i]) fail();
        }
    }

    private void assertSameData(byte[] data1, byte[] data2, int n) {
        if (data1 == null || data2 == null) fail();
        for (int i = 0; i < n; i++) {
            if (data1[i] != data2[i]) fail();
        }
    }
}
