package io.eguan.iscsisrv; /* * #%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.iscsisrv.IscsiDevice; import io.eguan.iscsisrv.IscsiServer; import io.eguan.iscsisrv.IscsiTarget; import java.io.IOException; import java.net.InetAddress; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; import org.jscsi.initiator.Configuration; import org.jscsi.initiator.Initiator; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; /** * Test error on read and write request. When an initiator requests read or write on a jSCSI target, if an error * occurred on the Target side, the Target does not handle the error properly and breaks the connection * * TODO: Fix read request and finish test TODO: Add a test with a write request with a failing write operation on the * device * * @author oodrive * @author ebredzinski * */ @RunWith(value = Parameterized.class) public class IscsiServerExceptionTest { /** TargetName (server) for the initiator (see unit test initiator config file) */ private static String TARGET_NAME = "test-eguan"; /** TargetName (device) for the initiator (see unit test initiator config file) */ private static String TARGET_DEVICE_IQN = "iqn.2000-06.com.oodrive:test-target"; private static int BLOCK_SIZE = 512; private static int BLOCK_COUNT = 1024; private static int FAIL_VAL_IO_EXCEPTION = 2 * BLOCK_SIZE; private static int FAIL_VAL_RUNTIME_EXCEPTION = 4 * BLOCK_SIZE; private final int testFailValue; IscsiServer server; final class TestIscsiDevice implements IscsiDevice { @Override public void close() throws IOException { // NOP } @Override public boolean isReadOnly() { return false; } @Override public long getSize() { return BLOCK_COUNT * BLOCK_SIZE; } @Override public int getBlockSize() { return BLOCK_SIZE; } @Override public void read(final ByteBuffer bytes, final int length, final long storageIndex) throws IOException { if (storageIndex == FAIL_VAL_IO_EXCEPTION) { throw new IOException("Test IOException"); } else if (storageIndex == FAIL_VAL_RUNTIME_EXCEPTION) { throw new RuntimeException("Test IOException"); } } @Override public void write(final ByteBuffer bytes, final int length, final long storageIndex) throws IOException { } } public IscsiServerExceptionTest(final Integer param) { this.testFailValue = param.intValue(); } @Parameters public static Collection<Object[]> data() { final Object[][] data = new Object[][] { { Integer.valueOf(FAIL_VAL_IO_EXCEPTION) }, { Integer.valueOf(FAIL_VAL_RUNTIME_EXCEPTION) } }; return Arrays.asList(data); } @Before public void initServerMBean() throws Exception { server = new IscsiServer(InetAddress.getLoopbackAddress()); } @Test public void testTargetReadDevice() throws Exception { Assert.assertFalse(server.isStarted()); // create a mock on the device final IscsiDevice mIscsiDevice = new TestIscsiDevice(); // Add target device final IscsiTarget target = IscsiTarget.newIscsiTarget(TARGET_DEVICE_IQN, null, mIscsiDevice); Assert.assertNull(server.addTarget(target)); server.start(); try { Assert.assertTrue(server.isStarted()); final Configuration configuration = Configuration.create(Initiator.class.getResource("/jscsi.xsd"), getClass().getResource("/iscsisrv-tst-config.xml")); final Initiator initiator = new Initiator(configuration); boolean closeSession = false; initiator.createSession(TARGET_NAME); try { closeSession = true; final ByteBuffer dst = ByteBuffer.wrap(new byte[BLOCK_SIZE]); final int logicalBlockAddress = testFailValue / BLOCK_SIZE; final long transferLength = BLOCK_SIZE; initiator.read(TARGET_NAME, dst, logicalBlockAddress, transferLength); } catch (final Throwable t) { closeSession = false; // TODO: fail if an exception is thrown // AssertionFailedError afe = new AssertionFailedError("Unexpected exception"); // afe.initCause(t); // throw afe; } finally { if (closeSession) { initiator.closeSession(TARGET_NAME); } } Assert.assertSame(target, server.removeTarget(TARGET_DEVICE_IQN)); Assert.assertNull(server.removeTarget(TARGET_DEVICE_IQN)); } finally { server.stop(); } } }