SslStreamConnectionValidationTestCase.java

/*
 * JBoss, Home of Professional Open Source.
 *
 * Copyright 2013 Red Hat, Inc. and/or its affiliates, and individual
 * contributors as indicated by the @author tags.
 *
 * 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 org.xnio.ssl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;

import org.junit.After;
import org.junit.Test;
import org.xnio.ssl.mock.SSLEngineMock;

/**
 * Test invalid scenarios involving the SSL connection.
 * 
 * @author <a href="mailto:frainone@redhat.com">Flavia Rainone</a>
 *
 */
public class SslStreamConnectionValidationTestCase extends AbstractSslConnectionTest {

    @After @Override
    public void checkContext() {
        // do not check context... not all methods will be invoked on sessions created for invalid scenarios
    }

    @Test
    public void writeAfterShutdown() throws IOException {
        conduitMock.setReadData(SSLEngineMock.CLOSE_MSG);
        conduitMock.enableReads(true);
        sinkConduit.terminateWrites();

        final ByteBuffer buffer = ByteBuffer.allocate(10);
        buffer.put("MSG!!!!!!!".getBytes("UTF-8")).flip();
        boolean failed = false;
        try {
            sinkConduit.write(buffer);
        } catch (ClosedChannelException e) {
            failed = true;
        }
        assertTrue(failed);
    }

    @Test
    public void invalidWriteBufferArray() throws IOException {
        final ByteBuffer buffer = ByteBuffer.allocate(10);
        buffer.put("invalid".getBytes("UTF-8")).flip();
        // the conduit should simply return 0 if length is 0 or a negative number
        assertEquals(0, sinkConduit.write(new ByteBuffer[]{buffer}, 0, 0));
        assertEquals(0, sinkConduit.write(new ByteBuffer[]{buffer}, 0, -1));
        // conduit should throw ArrayIndexOutOfBoundsException if position is < 0, or if length is larger than it should
        boolean failed = false;
        try {
            assertEquals(0, sinkConduit.write(new ByteBuffer[] { buffer }, -1, 1));
        } catch (ArrayIndexOutOfBoundsException e) {
            failed = true;
        }
        assertTrue(failed);
        failed = false;
        try {
            assertEquals(0, sinkConduit.write(new ByteBuffer[] { buffer }, 0, 2));
        } catch (ArrayIndexOutOfBoundsException e) {
            failed = true;
        }
        assertTrue(failed);
    }

    @Test
    public void writeNullBuffer() throws IOException {
        // null buffer
        boolean failed = false;
        try {
            sinkConduit.write((ByteBuffer) null);
        } catch (NullPointerException e) {
            failed = true;
        }
        assertTrue(failed);
        // null buffer array
        failed = false;
        try {
            sinkConduit.write((ByteBuffer[]) null, 4, 20);
        } catch (NullPointerException e) {
            failed = true;
        }
        assertTrue(failed);
        // null buffer in buffer array
        failed = false;
        try {
            sinkConduit.write(new ByteBuffer[] {null}, 0, 1);
        } catch (NullPointerException e) {
            failed = true;
        }
        assertTrue(failed);
    }

    @Test
    public void invalidReadBufferArray() throws IOException {
        conduitMock.setReadData("invalid read buffer array");
        conduitMock.enableReads(true);
        final ByteBuffer buffer = ByteBuffer.allocate(10);
        // the conduit should simply return 0 if length is 0
        assertEquals(0, sourceConduit.read(new ByteBuffer[]{buffer}, 0, 0));
        // conduit should throw ArrayIndexOutOfBoundsException if offs or len is < 0, or if length is larger than it should
        boolean failed = false;
        try {
            assertEquals(0, sourceConduit.read(new ByteBuffer[]{buffer}, 0, -1));
        } catch (ArrayIndexOutOfBoundsException e) {
            failed = true;
        }
        assertTrue(failed);
        failed = false;
        try {
            assertEquals(0, sourceConduit.read(new ByteBuffer[]{buffer}, -1, 1));
        } catch (ArrayIndexOutOfBoundsException e) {
            failed = true;
        }
        assertTrue(failed);
        failed = false;
        try {
            sourceConduit.read(new ByteBuffer[]{buffer}, 0, 2);
        } catch (ArrayIndexOutOfBoundsException e) {
            failed = true;
        }
        assertTrue(failed);
        failed = false;
        try {
            sourceConduit.read(new ByteBuffer[0], 0, 50);
        } catch (ArrayIndexOutOfBoundsException e) {
            failed = true;
        }
        assertTrue(failed);
    }

    @Test
    public void readToNullBuffer() throws IOException {
        conduitMock.setReadData("null read buffer");
        conduitMock.enableReads(true);
        // read to a null buffer
        boolean failed = false;
        try {
            sourceConduit.read((ByteBuffer) null);
        } catch (NullPointerException e) {
            failed = true;
        }
        assertTrue(failed);
        // read to a null buffer array
        failed = false;
        try {
            sourceConduit.read((ByteBuffer[]) null, 1, 3);
        } catch (NullPointerException e) {
            failed = true;
        }
        assertTrue(failed);
        // read to a null buffer in a buffer array
        failed = false;
        try {
            sourceConduit.read(new ByteBuffer[]{null}, 0, 1);
        } catch (NullPointerException e) {
            failed = true;
        }
        assertTrue(failed);
    }

    @Test
    public void terminateWritesCantFlush() throws IOException {
        conduitMock.enableFlush(false);
        ByteBuffer buffer = ByteBuffer.allocate(10);
        buffer.put("abc".getBytes("UTF-8")).flip();
        sinkConduit.write(buffer);
        sinkConduit.terminateWrites();
        assertWrittenMessage("abc", SSLEngineMock.CLOSE_MSG);
    }
}