package io.eguan.vvr.repository.core.api;
/*
* #%L
* Project eguan
* %%
* Copyright (C) 2012 - 2017 Oodrive
* %%
* 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.
* #L%
*/
import io.eguan.utils.ByteBuffers;
import io.eguan.utils.ByteBuffers.ByteBufferFactory;
import io.eguan.vvr.repository.core.api.Device;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.Random;
import junit.framework.AssertionFailedError;
import org.junit.Assert;
import org.junit.Test;
/**
*
* Unit tests on device with Ibs that have error.
*
* @author oodrive
* @author llambert
*
*/
public class TestDeviceIoErr extends TestDeviceAbstract {
public TestDeviceIoErr() {
super(true);
}
@Test
public void testMultiWriteErrReadArray() throws IOException {
testMultiWriteErrRead(ByteBuffers.FACTORY_BYTE_ARRAY);
}
@Test
public void testMultiWriteErrReadDirect() throws IOException {
testMultiWriteErrRead(ByteBuffers.FACTORY_BYTE_DIRECT);
}
/**
* Write, re-write with failure than read first written blocks. Take a snapshot to have block coming from a
* different NRS file.
*
* @param factory
* @throws IOException
*/
private void testMultiWriteErrRead(final ByteBufferFactory factory) throws IOException {
final int bufLen = deviceBlockSize * 7;
final byte[] buf1 = new byte[bufLen];
final byte[] buf2 = new byte[bufLen];
final Random random = new SecureRandom();
random.nextBytes(buf1);
random.nextBytes(buf2);
final ByteBuffer byteBuf1 = factory.newByteBuffer(buf1);
final ByteBuffer byteBuf2 = factory.newByteBuffer(buf2);
try (Device.ReadWriteHandle handle = device.open(true)) {
// Make sure there are partial IOs
final long position = deviceBlockSize / 2;
final int bufOffset = 0;
final int bufLength = bufLen;
// Write first blocks
handle.write(byteBuf1, bufOffset, bufLength, position);
{
// Read blocks: should be equals to the first ones
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBuf1.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBuf1, byteBufRead);
}
// Write second blocks at the same position: should fail
{
try {
handle.write(byteBuf2, bufOffset, bufLength, position);
throw new AssertionFailedError("Should not be reached");
}
catch (final IOException e) {
// OK
}
}
// Read blocks: should be equals to the first ones
{
// Read blocks: should be equals to the first ones
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBuf1.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBuf1, byteBufRead);
}
// Take snapshot to have blocks coming from another NRS file
device.createSnapshot();
// Write second blocks at the same position: should fail again
{
try {
handle.write(byteBuf2, bufOffset, bufLength, position);
throw new AssertionFailedError("Should not be reached");
}
catch (final IOException e) {
// OK
}
}
// Read blocks: should be equals to the first ones
{
// Read blocks: should be equals to the first ones
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBuf1.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBuf1, byteBufRead);
}
}
}
/**
* First write fails on an empty device, than read blocks that should be filled with 0.
*
* @throws IOException
*/
@Test
public void testMultiWriteErrReadZeroArray() throws IOException {
testMultiWriteErrReadZero(ByteBuffers.FACTORY_BYTE_ARRAY);
}
@Test
public void testMultiWriteErrReadZeroDirect() throws IOException {
testMultiWriteErrReadZero(ByteBuffers.FACTORY_BYTE_DIRECT);
}
private void testMultiWriteErrReadZero(final ByteBufferFactory factory) throws IOException {
final int bufLen = deviceBlockSize * 10;
final byte[] buf1 = new byte[bufLen];
final Random random = new SecureRandom();
random.nextBytes(buf1);
final ByteBuffer byteBuf1 = factory.newByteBuffer(buf1);
final ByteBuffer byteBufRef = factory.newByteBuffer(bufLen);
byteBufRef.position(bufLen);
try (Device.ReadWriteHandle handle = device.open(true)) {
// Make sure there are partial IOs
final long position = deviceBlockSize / 2;
final int bufOffset = 0;
final int bufLength = bufLen;
// Write first blocks: should fail
{
try {
handle.write(byteBuf1, bufOffset, bufLength, position);
throw new AssertionFailedError("Should not be reached");
}
catch (final IOException e) {
// OK
}
}
// Read blocks: should be full of 0
{
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBufRef.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBufRef, byteBufRead);
}
// Take snapshot to have a previous NRS file
device.createSnapshot();
// Write first blocks: should fail again
{
try {
handle.write(byteBuf1, bufOffset, bufLength, position);
throw new AssertionFailedError("Should not be reached");
}
catch (final IOException e) {
// OK
}
}
// Read blocks: should be full of 0
{
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBufRef.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBufRef, byteBufRead);
}
}
}
/**
* Test of data re-write, but on a single full write.
*
* @throws IOException
*/
@Test
public void testSingleWriteFullErrReadArray() throws IOException {
testSingleWriteErrRead(deviceBlockSize, deviceBlockSize, ByteBuffers.FACTORY_BYTE_ARRAY);
}
@Test
public void testSingleWriteFullErrReadDirect() throws IOException {
testSingleWriteErrRead(deviceBlockSize, deviceBlockSize, ByteBuffers.FACTORY_BYTE_DIRECT);
}
/**
* Test of data write failure, but on a single full write.
*
* @throws IOException
*/
@Test
public void testSingleWriteFullErrReadZeroArray() throws IOException {
testSingleWriteErrReadZero(deviceBlockSize, deviceBlockSize, ByteBuffers.FACTORY_BYTE_ARRAY);
}
@Test
public void testSingleWriteFullErrReadZeroDirect() throws IOException {
testSingleWriteErrReadZero(deviceBlockSize, deviceBlockSize, ByteBuffers.FACTORY_BYTE_DIRECT);
}
/**
* Test of data re-write, but on a single partial write.
*
* @throws IOException
*/
@Test
public void testSingleWritePartialErrReadArray() throws IOException {
testSingleWriteErrRead(deviceBlockSize / 3, deviceBlockSize / 10, ByteBuffers.FACTORY_BYTE_ARRAY);
}
@Test
public void testSingleWritePartialErrReadDirect() throws IOException {
testSingleWriteErrRead(deviceBlockSize / 3, deviceBlockSize / 10, ByteBuffers.FACTORY_BYTE_DIRECT);
}
/**
* Test of data write failure, but on a single partial write.
*
* @throws IOException
*/
@Test
public void testSingleWritePartialErrReadZeroArray() throws IOException {
testSingleWriteErrReadZero(deviceBlockSize / 3, deviceBlockSize / 10, ByteBuffers.FACTORY_BYTE_ARRAY);
}
@Test
public void testSingleWritePartialErrReadZeroDirect() throws IOException {
testSingleWriteErrReadZero(deviceBlockSize / 3, deviceBlockSize / 10, ByteBuffers.FACTORY_BYTE_DIRECT);
}
private void testSingleWriteErrRead(final int bufLen, final long position, final ByteBufferFactory factory)
throws IOException {
final byte[] buf1 = new byte[bufLen];
final Random random = new SecureRandom();
final int bufOffset = 0;
int writeCount = 0;
try (Device.ReadWriteHandle handle = device.open(true)) {
ByteBuffer byteBufPrev = null;
while (true) {
// New contents
random.nextBytes(buf1);
final ByteBuffer byteBufCurrent = factory.newByteBuffer(buf1);
// Write
try {
handle.write(byteBufCurrent, bufOffset, bufLen, position);
writeCount++;
// Read blocks: should be equals to the current one
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBufCurrent.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBufCurrent, byteBufRead);
// Keep previous buffer for the IOException to come
byteBufPrev = byteBufCurrent;
}
catch (final IOException e) {
// Write count: must fail after 9 writes (see
// TestValidIbsConfigurationContext.ContextTestHelperIbsError)
Assert.assertEquals(9, writeCount);
// Read blocks: should be equals to previous
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBufPrev.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBufPrev, byteBufRead);
// Test done
break;
}
}
}
}
private void testSingleWriteErrReadZero(final int bufLen, long position, final ByteBufferFactory factory)
throws IOException {
final byte[] buf1 = new byte[bufLen];
final Random random = new SecureRandom();
final ByteBuffer byteBufRef = factory.newByteBuffer(bufLen);
byteBufRef.position(bufLen);
final int bufOffset = 0;
final int bufLength = bufLen;
int writeCount = 0;
try (Device.ReadWriteHandle handle = device.open(true)) {
while (true) {
position += deviceBlockSize;
// Switch buffers and fill current with new bytes
random.nextBytes(buf1);
final ByteBuffer byteBufCurrent = factory.newByteBuffer(buf1);
// Write
try {
handle.write(byteBufCurrent, bufOffset, bufLength, position);
writeCount++;
// Read blocks: should be equals to the current one
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBufCurrent.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBufCurrent, byteBufRead);
}
catch (final IOException e) {
// Write count: must fail after 9 writes (see
// TestValidIbsConfigurationContext.ContextTestHelperIbsError)
Assert.assertEquals(9, writeCount);
final ByteBuffer byteBufRead = factory.newByteBuffer(bufLen);
handle.read(byteBufRead, bufOffset, bufLen, position);
// Check position and compare
Assert.assertEquals(bufLen, byteBufRef.position());
Assert.assertEquals(bufLen, byteBufRead.position());
ByteBuffers.assertEqualsByteBuffers(byteBufRef, byteBufRead);
// Test done
break;
}
}
}
}
}