/** * Copyright (c) 2012, University of Konstanz, Distributed Systems Group * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of Konstanz nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jscsi.parser.login; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import org.testng.annotations.Test; import java.io.IOException; import java.nio.ByteBuffer; import java.security.DigestException; import org.jscsi.exception.InternetSCSIException; import org.jscsi.parser.OperationCode; import org.jscsi.parser.ProtocolDataUnitTest; import org.jscsi.parser.datasegment.OperationalTextKey; import org.jscsi.parser.datasegment.SettingsMap; import org.jscsi.parser.login.ISID.Format; import org.jscsi.utils.WiresharkMessageParser; /** * Testing the correctness of the LoginResponseParser. * * @author Volker Wildi */ public class LoginResponseParserTest extends ProtocolDataUnitTest { /** * Valid Test Case with the following expected values. <blockquote> * Immediate Flag = <code>false</code><br/> * Operation Code = <code>LOGIN_RESPONSE</code> <br/> * Final Flag (Transit Flag) = <code>false</code><br/> * Continue Flag = <code>false</code><br/> * CSG = <code>LoginStage.SECURITY_NEGOTIATION</code> <br/> * NSG = <code>LoginStage.SECURITY_NEGOTIATION</code><br> * minVersion = <code>0x0002</code><br/> * maxVersion = <code>0x0002</code> <br/> * <br/> * TotalAHSLength = <code>0x00000000</code><br/> * DataSegmentLength = <code>0x00000010</code><br/> * <b>ISID:</b><br/> * <blockquote> t = <code>ISID.OUI_FORMAT</code><br/> * a = <code>0x00</code><br/> * b = <code>0x0000</code><br/> * c = <code>0x00</code><br/> * d = <code>0xABCD</code> <br/> * <br/> * </blockquote> InitiatorTaskTag = <code>0xC8D04B81</code><br/> * TSIH = <code>0x0000</code><br/> * CID = <code>0x0000</code><br/> * StatSN = <code>0x00000000</code><br/> * ExpCmdSN = <code>0x00000001</code><br/> * MaxCmdSN = <code>0x00000008</code><br/> * Status = <code>SUCCESS</code> </br><br/> * <b>Key-Values:</b><br/> * AUTH_METHOD = <code>none</code><br/> * </blockquote> */ private static final String TEST_CASE_1 = "23 00 02 02 00 00 00 10 00 00 00 00 ab cd 00 01 " + "c8 d0 4b 81 00 00 00 00 00 00 00 00 00 00 00 01 " + "00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 " + "41 75 74 68 4d 65 74 68 6f 64 3d 4e 6f 6e 65 00 "; /** * Valid Test Case with the following expected values. <blockquote> * Immediate Flag = <code>false</code><br/> * Operation Code = <code>LOGIN_RESPONSE</code> <br/> * Final Flag (Transit Flag) = <code>true</code><br/> * Continue Flag = <code>false</code><br/> * CSG = <code>LoginStage.LOGIN_OPERATIONAL_NEGOTIATION</code><br/> * NSG = <code>LoginStage.FULL_FEATURE_PHASE</code><br> * minVersion = <code>0x0000</code><br/> * maxVersion = <code>0x0000</code> <br/> * <br/> * TotalAHSLength = <code>0x00000000</code><br/> * DataSegmentLength = <code>0x0000012C</code><br/> * <b>ISID:</b><br/> * <blockquote> t = <code>ISID.OUI_FORMAT</code><br/> * a = <code>0x00</code><br/> * b = <code>0x023D</code><br/> * c = <code>0x00</code><br/> * d = <code>0x0000</code> <br/> * <br/> * </blockquote> InitiatorTaskTag = <code>0x000A0000</code><br/> * TSIH = <code>0x0000</code><br/> * CID = <code>0x0000</code><br/> * StatSN = <code>0x00000000</code><br/> * ExpCmdSN = <code>0x00000000</code><br/> * MaxCmdSN = <code>0x00000001</code><br/> * Status = <code>SUCCESS</code> </br><br/> * <b>Key-Values:</b><br/> * TARGET_PORTAL_GROUP_TAG = <code>1</code> <br/> * HEADER_DIGEST = <code>None</code><br/> * DATA_DIGEST = <code>None</code><br/> * DEFAULT_TIME_2_WAIT = <code>2</code><br/> * DEFAULT_TIME_2_RETAIN = <code>0</code><br/> * IF_MARKER = <code>No</code> <br/> * OF_MARKER = <code>No</code><br/> * ERROR_RECOVERY_LEVEL = <code>0</code><br/> * INITIAL_R2T = <code>Yes</code><br/> * IMMEDIATE_DATA = <code>Yes</code><br/> * MAX_BURST_LENGTH = <code>262144</code><br/> * FIRST_BURST_LENGTH = <code>65536</code><br/> * MAX_OUTSTANDING_R2T = <code>1</code><br/> * MAX_CONNECTIONS = <code>1</code><br/> * DATA_PDU_IN_ORDER = <code>Yes</code><br/> * DATA_SEQUENCE_IN_ORDER = <code>Yes</code><br/> * </blockquote> */ private static final String TEST_CASE_2 = "23 87 00 00 00 00 01 2c 00 02 3d 00 00 00 01 00 " + "00 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 " + "54 61 72 67 65 74 50 6f 72 74 61 6c 47 72 6f 75 " + "70 54 61 67 3d 31 00 48 65 61 64 65 72 44 69 67 " + "65 73 74 3d 4e 6f 6e 65 00 44 61 74 61 44 69 67 " + "65 73 74 3d 4e 6f 6e 65 00 44 65 66 61 75 6c 74 " + "54 69 6d 65 32 57 61 69 74 3d 32 00 44 65 66 61 " + "75 6c 74 54 69 6d 65 32 52 65 74 61 69 6e 3d 30 " + "00 49 46 4d 61 72 6b 65 72 3d 4e 6f 00 4f 46 4d " + "61 72 6b 65 72 3d 4e 6f 00 45 72 72 6f 72 52 65 " + "63 6f 76 65 72 79 4c 65 76 65 6c 3d 30 00 49 6e " + "69 74 69 61 6c 52 32 54 3d 59 65 73 00 49 6d 6d " + "65 64 69 61 74 65 44 61 74 61 3d 59 65 73 00 4d " + "61 78 42 75 72 73 74 4c 65 6e 67 74 68 3d 32 36 " + "32 31 34 34 00 46 69 72 73 74 42 75 72 73 74 4c " + "65 6e 67 74 68 3d 36 35 35 33 36 00 4d 61 78 4f " + "75 74 73 74 61 6e 64 69 6e 67 52 32 54 3d 31 00 " + "4d 61 78 43 6f 6e 6e 65 63 74 69 6f 6e 73 3d 31 " + "00 44 61 74 61 50 44 55 49 6e 4f 72 64 65 72 3d " + "59 65 73 00 44 61 74 61 53 65 71 75 65 6e 63 65 " + "49 6e 4f 72 64 65 72 3d 59 65 73 00"; /** * This test case validates the parsing process. * * @throws IOException * This exception should be never thrown. * @throws InternetSCSIException * This exception should be never thrown. * @throws DigestException * This exception should be never thrown. */ @Test public void testDeserialize() throws IOException, InternetSCSIException, DigestException { SettingsMap expectedKeyValuePair = new SettingsMap(); expectedKeyValuePair.add(OperationalTextKey.AUTH_METHOD, "None"); super.setUp(TEST_CASE_1); // final flag is here the transit flag super.testDeserialize(false, false, OperationCode.LOGIN_RESPONSE, 0x00000000, 0x00000010, 0xC8D04B81); super.testDataSegment(expectedKeyValuePair); assertTrue(recognizedParser instanceof LoginResponseParser); LoginResponseParser parser = (LoginResponseParser)recognizedParser; // test login response fields assertFalse(parser.isContinueFlag()); assertEquals(LoginStage.SECURITY_NEGOTIATION, parser.getCurrentStageNumber()); assertEquals(LoginStage.SECURITY_NEGOTIATION, parser.getNextStageNumber()); assertEquals(0x0002, parser.getActiveVersion()); assertEquals(0x0002, parser.getMaxVersion()); // test ISID fields ISID expectedISID = new ISID(Format.OUI_FORMAT, (byte)0x00, (short)0x0000, (byte)0x00, (short)0xABCD); assertTrue(expectedISID.equals(parser.getInitiatorSessionID())); assertEquals(0x00000000, parser.getStatusSequenceNumber()); assertEquals(0x00000001, parser.getExpectedCommandSequenceNumber()); assertEquals(0x00000008, parser.getMaximumCommandSequenceNumber()); assertEquals(LoginStatus.SUCCESS, parser.getStatus()); } /** * This test case validates the parsing process. * * @throws IOException * This exception should be never thrown. * @throws InternetSCSIException * This exception should be never thrown. * @throws DigestException * This exception should be never thrown. */ @Test public void testDeserialize2() throws IOException, InternetSCSIException, DigestException { SettingsMap expectedKeyValuePair = new SettingsMap(); expectedKeyValuePair.add(OperationalTextKey.TARGET_PORTAL_GROUP_TAG, "1"); expectedKeyValuePair.add(OperationalTextKey.HEADER_DIGEST, "None"); expectedKeyValuePair.add(OperationalTextKey.DATA_DIGEST, "None"); expectedKeyValuePair.add(OperationalTextKey.DEFAULT_TIME_2_WAIT, "2"); expectedKeyValuePair.add(OperationalTextKey.DEFAULT_TIME_2_RETAIN, "0"); expectedKeyValuePair.add(OperationalTextKey.IF_MARKER, "No"); expectedKeyValuePair.add(OperationalTextKey.OF_MARKER, "No"); expectedKeyValuePair.add(OperationalTextKey.ERROR_RECOVERY_LEVEL, "0"); expectedKeyValuePair.add(OperationalTextKey.INITIAL_R2T, "Yes"); expectedKeyValuePair.add(OperationalTextKey.IMMEDIATE_DATA, "Yes"); expectedKeyValuePair.add(OperationalTextKey.MAX_BURST_LENGTH, "262144"); expectedKeyValuePair.add(OperationalTextKey.FIRST_BURST_LENGTH, "65536"); expectedKeyValuePair.add(OperationalTextKey.MAX_OUTSTANDING_R2T, "1"); expectedKeyValuePair.add(OperationalTextKey.MAX_CONNECTIONS, "1"); expectedKeyValuePair.add(OperationalTextKey.DATA_PDU_IN_ORDER, "Yes"); expectedKeyValuePair.add(OperationalTextKey.DATA_SEQUENCE_IN_ORDER, "Yes"); super.setUp(TEST_CASE_2); // final flag is here the transit flag super.testDeserialize(false, true, OperationCode.LOGIN_RESPONSE, 0x00000000, 0x0000012C, 0x000A0000); super.testDataSegment(expectedKeyValuePair); assertTrue(recognizedParser instanceof LoginResponseParser); LoginResponseParser parser = (LoginResponseParser)recognizedParser; // test login response fields assertFalse(parser.isContinueFlag()); assertEquals(LoginStage.LOGIN_OPERATIONAL_NEGOTIATION, parser.getCurrentStageNumber()); assertEquals(LoginStage.FULL_FEATURE_PHASE, parser.getNextStageNumber()); assertEquals(0x0000, parser.getActiveVersion()); assertEquals(0x0000, parser.getMaxVersion()); ISID expectedISID = new ISID(Format.OUI_FORMAT, (byte)0x00, (short)0x023D, (byte)0x00, (short)0x0000); assertTrue(expectedISID.equals(parser.getInitiatorSessionID())); assertEquals(0x00000000, parser.getStatusSequenceNumber()); assertEquals(0x00000000, parser.getExpectedCommandSequenceNumber()); assertEquals(0x00000001, parser.getMaximumCommandSequenceNumber()); assertEquals(LoginStatus.SUCCESS, parser.getStatus()); } /** * This test case validates the serialization process. * * @throws InternetSCSIException * This exception should be never thrown. * @throws IOException * This exception should be never thrown. * @throws DigestException * This exception should be never thrown. */ @Test public void testSerialize1() throws InternetSCSIException, IOException, DigestException { super.setUp(TEST_CASE_1); ByteBuffer expectedResult = WiresharkMessageParser.parseToByteBuffer(TEST_CASE_1); assertTrue(expectedResult.equals(protocolDataUnit.serialize())); } /** * This test case validates the serialization process. * * @throws InternetSCSIException * This exception should be never thrown. * @throws IOException * This exception should be never thrown. * @throws DigestException * This exception should be never thrown. */ @Test public void testSerialize2() throws InternetSCSIException, IOException, DigestException { super.setUp(TEST_CASE_2); ByteBuffer expectedResult = WiresharkMessageParser.parseToByteBuffer(TEST_CASE_2); assertTrue(expectedResult.equals(protocolDataUnit.serialize())); } }