package com.github.marschall.memoryfilesystem;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class MemoryContentsBoundaryTest {
private final int initialOffset;
private final int initialBlocks;
private final int toWrite;
private MemoryFile contents;
public MemoryContentsBoundaryTest(int initialOffset, int initialBlocks, int twoWrite) {
this.initialOffset = initialOffset;
this.toWrite = twoWrite;
this.initialBlocks = initialBlocks;
}
@Parameters(name = "initialOffset: {0}, initialBlocks: {1}, twoWrite: {2}")
public static List<Object[]> parameters() {
int blockSize = MemoryInode.BLOCK_SIZE;
List<Object[]> parameters = new ArrayList<>();
for (int initialOffset : new int[]{0, blockSize - 2, blockSize - 1, blockSize, blockSize + 1, blockSize + 2}) {
for (int initialBlockSize = 0; initialBlockSize < 10; initialBlockSize++) {
for (int multiplier = 1; multiplier < 5; multiplier++) {
int offset = blockSize * multiplier;
parameters.add(new Object[]{initialOffset, initialBlockSize, offset - 2});
parameters.add(new Object[]{initialOffset, initialBlockSize, offset - 1});
parameters.add(new Object[]{initialOffset, initialBlockSize, offset});
parameters.add(new Object[]{initialOffset, initialBlockSize, offset + 1});
parameters.add(new Object[]{initialOffset, initialBlockSize, offset + 2});
}
}
}
return parameters;
}
@Before
public void setUp() {
this.contents = new MemoryFile("", EntryCreationContext.empty(), this.initialBlocks);
}
@Test
public void boundaryWrapping() throws IOException {
Path path = new MockPath();
SeekableByteChannel channel = this.contents.newChannel(true, true, false, path);
byte[] initial = new byte[this.initialOffset];
channel.write(ByteBuffer.wrap(initial));
byte[] data = new byte[this.toWrite];
data[data.length - 1] = 9;
data[data.length - 2] = 8;
data[data.length - 3] = 7;
data[2] = 3;
data[1] = 2;
data[0] = 1;
ByteBuffer src = ByteBuffer.wrap(data);
channel.write(src);
assertEquals(this.toWrite + this.initialOffset, channel.size());
assertEquals(this.toWrite + this.initialOffset, channel.position());
// one element tests
// read last element
byte[] oneElement = new byte[1];
ByteBuffer dst = ByteBuffer.wrap(oneElement);
channel.position(channel.size() - 1L);
assertEquals(1, channel.read(dst));
assertArrayEquals(new byte[]{9}, oneElement);
// read first element
dst.rewind();
long startOfWrite = channel.size() - this.toWrite;
channel.position(startOfWrite);
assertEquals(1, channel.read(dst));
assertArrayEquals(new byte[]{1}, oneElement);
// two element tests
// read last two elements
byte[] twoElements = new byte[2];
dst = ByteBuffer.wrap(twoElements);
channel.position(channel.size() - 2L);
assertEquals(2, channel.read(dst));
assertArrayEquals(new byte[]{8, 9}, twoElements);
// read first two elements
dst.rewind();
channel.position(startOfWrite);
assertEquals(2, channel.read(dst));
assertArrayEquals(new byte[]{1, 2}, twoElements);
// read last three elements
byte[] threeElements = new byte[3];
dst = ByteBuffer.wrap(threeElements);
channel.position(channel.size() - 3L);
assertEquals(3, channel.read(dst));
assertArrayEquals(new byte[]{7, 8, 9}, threeElements);
// read first two elements
dst.rewind();
channel.position(startOfWrite);
assertEquals(3, channel.read(dst));
assertArrayEquals(new byte[]{1, 2, 3}, threeElements);
// read the full data back
byte[] readBack = new byte[this.toWrite];
dst = ByteBuffer.wrap(readBack);
channel.position(channel.size() - this.toWrite);
assertEquals(this.toWrite, channel.read(dst));
assertEquals(1, readBack[0]);
assertEquals(2, readBack[1]);
assertEquals(3, readBack[2]);
assertEquals(7, readBack[readBack.length - 3]);
assertEquals(8, readBack[readBack.length - 2]);
assertEquals(9, readBack[readBack.length - 1]);
}
}