/*
 * Copyright (c) 2013. Jordan Williams
 *
 * 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.jordanwilliams.heftydb.test.unit.io;


import com.jordanwilliams.heftydb.io.ChannelDataFile;
import com.jordanwilliams.heftydb.io.DataFile;
import com.jordanwilliams.heftydb.io.MappedDataFile;
import com.jordanwilliams.heftydb.test.base.FileTest;
import com.jordanwilliams.heftydb.test.helper.TestFileHelper;
import com.jordanwilliams.heftydb.util.Sizes;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class DataFileTest extends FileTest {

    private static final ByteBuffer TEST_BYTES = ByteBuffer.wrap("I am some very impressive test data".getBytes());
    private static final ByteBuffer MORE_TEST_BYTES = ByteBuffer.wrap("Test data is very interesting".getBytes());

    private final Path testFile = TestFileHelper.TEMP_PATH.resolve("testfile");


    @Test
    public void concurrencyTest() throws Exception {
        final int threadCount = 32;
        final int iterationCount = 1000;
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        final DataFile dataFile = ChannelDataFile.open(testFile);
        final AtomicInteger counter = new AtomicInteger();

        for (int i = 0; i < threadCount; i++){
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < iterationCount; i++){
                        try {
                            dataFile.appendInt(counter.getAndIncrement());
                        } catch (IOException e){
                            throw new RuntimeException(e);
                        }
                    }
                }
            });
        }

        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);

        int fileOffset = 0;
        int[] readValues = new int[threadCount * iterationCount];

        for (int i = 0; i < threadCount * iterationCount; i++){
            int read = dataFile.readInt(fileOffset);
            readValues[read] += 1;
            fileOffset += Sizes.INT_SIZE;
        }

        for (int i = 0; i < readValues.length; i++){
            Assert.assertEquals("All values appear once", 1, readValues[i]);
        }
    }

    @Test
    public void mutableDataFileTest() throws IOException {
        TEST_BYTES.rewind();
        MORE_TEST_BYTES.rewind();

        ChannelDataFile file = ChannelDataFile.open(testFile);

        file.append(TEST_BYTES);
        file.append(MORE_TEST_BYTES);

        TEST_BYTES.rewind();
        file.write(TEST_BYTES, file.size());

        ByteBuffer readBuffer = ByteBuffer.allocate(TEST_BYTES.capacity());
        file.read(readBuffer, 0);

        TEST_BYTES.rewind();
        readBuffer.rewind();

        Assert.assertEquals("Read bytes", TEST_BYTES, readBuffer);
        Assert.assertEquals("File size", (TEST_BYTES.capacity() * 2) + MORE_TEST_BYTES.capacity(), file.size());
    }

    @Test
    public void mutableDataFilePrimitiveTest() throws IOException {
        ChannelDataFile file = ChannelDataFile.open(testFile);

        file.appendInt(4);
        file.appendLong(8);
        file.writeInt(4, file.size());
        file.writeLong(8, file.size());

        Assert.assertEquals("Values match", 4, file.readInt(0));
        Assert.assertEquals("Values match", 8, file.readLong(4));
        Assert.assertEquals("Values match", 4, file.readInt(12));
        Assert.assertEquals("Values match", 8, file.readLong(16));
    }

    @Test
    public void mappedDataFileTest() throws IOException {
        TEST_BYTES.rewind();
        MORE_TEST_BYTES.rewind();

        FileChannel channel = FileChannel.open(testFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE);

        channel.write(TEST_BYTES);
        channel.write(MORE_TEST_BYTES);
        channel.close();

        MappedDataFile file = MappedDataFile.open(testFile);

        ByteBuffer readBuffer = ByteBuffer.allocate(TEST_BYTES.capacity());
        file.read(readBuffer, 0);
        readBuffer.flip();

        TEST_BYTES.rewind();

        Assert.assertEquals("Read bytes", TEST_BYTES, readBuffer);
        Assert.assertEquals("File size", TEST_BYTES.capacity() + MORE_TEST_BYTES.capacity(), file.size());
    }
}

@@ -753,61 +753,8 @@
 le;%0A
-import com.jordanwilliams.heftydb.io.MappedDataFile;%0A
 impo
@@ -1036,96 +1036,17 @@
 nio.
-channels.FileChannel;%0Aimport java.nio.file.Path;%0Aimport java.nio.file.StandardOpenOption
+file.Path
 ;%0Aim
@@ -4226,763 +4226,7 @@
    %7D
-%0A%0A    @Test%0A    public void mappedDataFileTest() throws IOException %7B%0A        TEST_BYTES.rewind();%0A        MORE_TEST_BYTES.rewind();%0A%0A        FileChannel channel = FileChannel.open(testFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE);%0A%0A        channel.write(TEST_BYTES);%0A        channel.write(MORE_TEST_BYTES);%0A        channel.close();%0A%0A        MappedDataFile file = MappedDataFile.open(testFile);%0A%0A        ByteBuffer readBuffer = ByteBuffer.allocate(TEST_BYTES.capacity());%0A        file.read(readBuffer, 0);%0A        readBuffer.flip();%0A%0A        TEST_BYTES.rewind();%0A%0A        Assert.assertEquals(%22Read bytes%22, TEST_BYTES, readBuffer);%0A        Assert.assertEquals(%22File size%22, TEST_BYTES.capacity() + MORE_TEST_BYTES.capacity(), file.size());%0A    %7D
 %0A%7D%0A

Delete test