com.unister.semweb.drums.file.RepairIndexTest.java Source code

Java tutorial

Introduction

Here is the source code for com.unister.semweb.drums.file.RepairIndexTest.java

Source

/* Copyright (C) 2012-2013 Unister GmbH
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
package com.unister.semweb.drums.file;

import java.io.File;
import java.nio.ByteBuffer;

import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.unister.semweb.drums.DRUMSParameterSet;
import com.unister.semweb.drums.file.HeaderIndexFile;
import com.unister.semweb.drums.file.AbstractHeaderFile.AccessMode;
import com.unister.semweb.drums.storable.TestStorable;

/**
 * Tests for the <code>repairIndex()</code> method of the {@link HeaderIndexFile}.
 * 
 * @author Nils Thieme
 * 
 */
public class RepairIndexTest {
    private static final String filename = "/tmp/indexRestorer.db";

    private DRUMSParameterSet<TestStorable> globalParameters;
    private int elementsPerChunk;

    /** Initialises the test by removing the test file. */
    @Before
    public void inititalise() throws Exception {
        FileUtils.deleteQuietly(new File(filename));
        globalParameters = new DRUMSParameterSet<TestStorable>(new TestStorable());
        elementsPerChunk = (int) (globalParameters.FILE_CHUNK_SIZE / globalParameters.getElementSize());
    }

    /** Only one element is written to the test file. */
    @Test
    public void simpleTest() throws Exception {
        makeTestWith(1);
    }

    /** A full chunk is written to the test file. */
    @Test
    public void oneFullChunk() throws Exception {
        makeTestWith(elementsPerChunk);
    }

    /** Several chunks are written to the test file. */
    @Test
    public void severalChunks() throws Exception {
        makeTestWith(7 * elementsPerChunk);
    }

    /**
     * Makes the real test with the given number of elements to handle. The test consists of the following parts:
     * <ul>
     * <li>Write the test data to the file</li>
     * <li>The index must not contain any element (for each element the index will return the pseudo chunk id -1)</li>
     * <li>The file is opened again and the index will be repaired.</li>
     * <li>It is examined whether each element has the chunk id within the index.</li>
     * </ul>
     * 
     * @param numberOfElements
     * @throws Exception
     */
    private void makeTestWith(int numberOfElements) throws Exception {
        TestStorable[] testdata = generateTestdata(numberOfElements);
        ByteBuffer writeData = convert(testdata);

        HeaderIndexFile<TestStorable> file = new HeaderIndexFile<TestStorable>(filename, AccessMode.READ_WRITE, 1,
                globalParameters);
        file.write(0, writeData);
        Assert.assertNotNull(file.getIndex());
        Assert.assertTrue(allElementNotInIndex(testdata, file));
        file.close();

        HeaderIndexFile<TestStorable> fileToIndex = new HeaderIndexFile<TestStorable>(filename,
                AccessMode.READ_WRITE, 1, globalParameters);
        fileToIndex.repairIndex();
        fileToIndex.close();

        HeaderIndexFile<TestStorable> fileWithIndex = new HeaderIndexFile<TestStorable>(filename,
                AccessMode.READ_WRITE, 1, globalParameters);
        Assert.assertTrue(isChunkId(testdata, fileWithIndex));
        fileWithIndex.close();
    }

    /**
     * Generates the given number of test data. The only difference of the {@link TestStorable} is their key (it is
     * increased by 1).
     */
    private TestStorable[] generateTestdata(int numberOfTestdata) {
        TestStorable[] result = new TestStorable[numberOfTestdata];
        for (int i = 0; i < numberOfTestdata; i++) {
            byte[] currentKey = transform(i + 1, globalParameters.getKeySize());
            TestStorable newData = new TestStorable();
            newData.setKey(currentKey);
            result[i] = newData;
        }
        return result;
    }

    /** Converts the given array of {@link TestStorable} to a consecutive {@link ByteBuffer}. */
    private ByteBuffer convert(TestStorable[] toConvert) {
        ByteBuffer converter = ByteBuffer.allocate(toConvert.length * globalParameters.getElementSize());
        for (TestStorable oneTestStorable : toConvert) {
            converter.put(oneTestStorable.toByteBuffer());
        }
        converter.flip();
        return converter;
    }

    /**
     * Converts the given <code>value</code> to a byte array representation. The final array has
     * <code>numberOfBytes</code>.
     */
    private byte[] transform(int value, int numberOfBytes) {
        ByteBuffer buffer = ByteBuffer.allocate(numberOfBytes);
        buffer.putInt(numberOfBytes - 4, value);
        return buffer.array();
    }

    /** Examines whether all the given {@link TestStorable} are located in the <code>expectedChunkId</code>. */
    private boolean isChunkId(TestStorable[] TestStorable, HeaderIndexFile<TestStorable> file) {
        for (int i = 0; i < TestStorable.length; i++) {
            int expectedChunkId = i / elementsPerChunk;
            TestStorable oneTestStorable = TestStorable[i];
            int chunkId = file.getIndex().getChunkId(oneTestStorable.getKey());
            if (chunkId != expectedChunkId) {
                System.out.println("Expected chunk id: " + expectedChunkId + " <-> Read chunk id: " + chunkId);
                return false;
            }
        }
        return true;
    }

    /** Examines whether all given <code>elements</code> are not indexed. */
    private boolean allElementNotInIndex(TestStorable[] elements, HeaderIndexFile<TestStorable> file) {
        for (TestStorable oneTestStorable : elements) {
            int currentChunkId = file.getIndex().getChunkId(oneTestStorable.getKey());
            if (currentChunkId != -1) {
                return false;
            }
        }
        return true;
    }
}