/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.qpid.tests.protocol.v1_0.transport.connection;

import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.both;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.hamcrest.Matchers.notNullValue;

import java.net.InetSocketAddress;

import org.junit.Test;

import org.apache.qpid.server.protocol.v1_0.type.UnsignedInteger;
import org.apache.qpid.server.protocol.v1_0.type.UnsignedShort;
import org.apache.qpid.server.protocol.v1_0.type.transport.AmqpError;
import org.apache.qpid.server.protocol.v1_0.type.transport.Close;
import org.apache.qpid.server.protocol.v1_0.type.transport.ConnectionError;
import org.apache.qpid.server.protocol.v1_0.type.transport.Error;
import org.apache.qpid.server.protocol.v1_0.type.transport.Open;
import org.apache.qpid.tests.utils.BrokerAdmin;
import org.apache.qpid.tests.protocol.v1_0.FrameTransport;
import org.apache.qpid.tests.protocol.v1_0.Interaction;
import org.apache.qpid.tests.protocol.v1_0.EmptyResponse;
import org.apache.qpid.tests.utils.BrokerAdminUsingTestBase;
import org.apache.qpid.tests.protocol.SpecificationTest;
import org.apache.qpid.tests.utils.BrokerSpecific;


public class OpenTest extends BrokerAdminUsingTestBase
{
    @Test
    @SpecificationTest(section = "1.3.4",
            description = "Open without mandatory fields should result in a decoding error.")
    public void emptyOpen() throws Exception
    {
        final InetSocketAddress addr = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.ANONYMOUS_AMQP);
        try (FrameTransport transport = new FrameTransport(addr).connect())
        {
            final Interaction interaction = transport.newInteraction();
            Open responseOpen = interaction.negotiateProtocol().consumeResponse()
                                           .openContainerId(null)
                                           .open().consumeResponse()
                                           .getLatestResponse(Open.class);
            assertThat(responseOpen.getContainerId(), is(notNullValue()));

            Close responseClose = interaction.consumeResponse().getLatestResponse(Close.class);

            // 2.7.9: If set, this field indicates that the connection is being closed due to an error condition.
            // The value of the field SHOULD contain details on the cause of the error.
            Error error = responseClose.getError();
            if (error != null)
            {
                assertThat(error.getCondition(), equalTo(AmqpError.DECODE_ERROR));
            }
        }
    }

    @Test
    @SpecificationTest(section = "2.4.1",
            description = "Each AMQP connection begins with an exchange of capabilities and limitations, "
                          + "including the maximum frame size.")
    public void successfulOpen() throws Exception
    {
        final InetSocketAddress addr = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.ANONYMOUS_AMQP);
        try (FrameTransport transport = new FrameTransport(addr).connect())
        {
            Interaction interaction = transport.newInteraction();
            Open responseOpen = interaction
                                         .negotiateProtocol().consumeResponse()
                                         .openContainerId("testContainerId")
                                         .open().consumeResponse()
                                         .getLatestResponse(Open.class);
            assertThat(responseOpen.getContainerId(), is(notNullValue()));
            assertThat(responseOpen.getMaxFrameSize().longValue(),
                       is(both(greaterThanOrEqualTo(0L)).and(lessThanOrEqualTo(UnsignedInteger.MAX_VALUE.longValue()))));
            assertThat(responseOpen.getChannelMax().intValue(),
                       is(both(greaterThanOrEqualTo(0)).and(lessThanOrEqualTo(UnsignedShort.MAX_VALUE.intValue()))));

            interaction.doCloseConnection();
        }
    }

    @Test
    @SpecificationTest(section = "2.4.5",
            description = "Implementations MUST be prepared to handle empty frames arriving on any valid channel")
    public void emptyFrame() throws Exception
    {
        final InetSocketAddress addr = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.ANONYMOUS_AMQP);
        try (FrameTransport transport = new FrameTransport(addr).connect())
        {
            Interaction interaction = transport.newInteraction();
            interaction.negotiateProtocol().consumeResponse()
                       .openContainerId("testContainerId")
                       .open().consumeResponse(Open.class)
                       .emptyFrame()
                       .doCloseConnection();
        }
    }

    @Test
    @SpecificationTest(section = "2.4.5",
            description = "Connections are subject to an idle timeout threshold.")
    public void idleTimeout() throws Exception
    {
        final InetSocketAddress addr = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.ANONYMOUS_AMQP);
        try (FrameTransport transport = new FrameTransport(addr).connect())
        {
            Interaction interaction = transport.newInteraction();
            final int idleTimeOut = 1000;
            Open responseOpen = interaction.negotiateProtocol().consumeResponse()
                                           .openContainerId("testContainerId")
                                           .openIdleTimeOut(idleTimeOut)
                                           .open().consumeResponse()
                                           .getLatestResponse(Open.class);

            final UnsignedInteger peerIdleTimeOut = responseOpen.getIdleTimeOut();
            assertThat(peerIdleTimeOut, is(anyOf(nullValue(), greaterThanOrEqualTo(UnsignedInteger.ZERO))));

            final int timeout = peerIdleTimeOut == null || peerIdleTimeOut.intValue() == 0
                    ? idleTimeOut
                    : peerIdleTimeOut.intValue();
            Thread.sleep(timeout);
            interaction.consumeResponse(EmptyResponse.class);
        }
    }

    @Test
    @SpecificationTest(section = "2.4.1",
            description = "The open frame can only be sent on channel 0. §2.7.1: A peer that receives a channel number"
                          + " outside the supported range MUST close the connection with the framing-error error-code.")
    public void failOpenOnChannelNotZero() throws Exception
    {
        final InetSocketAddress addr = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.ANONYMOUS_AMQP);
        try (FrameTransport transport = new FrameTransport(addr).connect())
        {
            final Interaction interaction = transport.newInteraction();
            Open responseOpen = interaction.negotiateProtocol().consumeResponse()
                                           .openContainerId("testContainerId")
                                           .connectionChannel(UnsignedShort.valueOf((short) 1))
                                           .open().consumeResponse()
                                           .getLatestResponse(Open.class);
            assertThat(responseOpen.getContainerId(), is(notNullValue()));

            Close responseClose = interaction.consumeResponse(Close.class).getLatestResponse(Close.class);

            // 2.7.9: If set, this field indicates that the connection is being closed due to an error condition.
            // The value of the field SHOULD contain details on the cause of the error.
            Error error = responseClose.getError();
            if (error != null)
            {
                assertThat(error.getCondition(), equalTo(ConnectionError.FRAMING_ERROR));
            }
        }
    }

    @Test
    @SpecificationTest(section = "2.7.1", description = "The name of the host (either fully qualified or relative) to which the sending peer is connecting")
    @BrokerSpecific(kind = BrokerAdmin.KIND_BROKER_J)
    public void failOpenOnNonExistingHostname() throws Exception
    {
        final InetSocketAddress addr = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.ANONYMOUS_AMQP);
        try (FrameTransport transport = new FrameTransport(addr).connect())
        {
            final Interaction interaction = transport.newInteraction();
            Open responseOpen = interaction.negotiateProtocol().consumeResponse()
                                           .openContainerId("testContainerId")
                                           .openHostname("non-existing-virtual-host-" + System.currentTimeMillis())
                                           .open().consumeResponse()
                                           .getLatestResponse(Open.class);
            assertThat(responseOpen.getContainerId(), is(notNullValue()));

            Close responseClose = interaction.consumeResponse().getLatestResponse(Close.class);
            assertThat(responseClose.getError(), is(notNullValue()));
            assertThat(responseClose.getError().getCondition(), equalTo(AmqpError.NOT_FOUND));
        }
    }
}
