/*
 * 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.tomcat.jdbc.test;

import java.sql.Connection;
import java.sql.SQLException;

import org.junit.Assert;
import org.junit.Test;

/**
 * If a connection is abandoned and closed,
 * then that should free up a spot in the pool, and other threads
 * that are waiting should not time out and throw an error but be
 * able to acquire a connection, since one was just released.
 */
public class StarvationTest extends DefaultTestCase {

    private void config() {
        datasource.getPoolProperties().setMaxActive(1);
        datasource.getPoolProperties().setMaxIdle(1);
        datasource.getPoolProperties().setInitialSize(1);
        datasource.getPoolProperties().setRemoveAbandoned(true);
        datasource.getPoolProperties().setRemoveAbandonedTimeout(5);
        datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500);
        datasource.getPoolProperties().setMaxWait(10000);
        datasource.getPoolProperties().setLogAbandoned(true);
    }

//    @Test
//    public void testDBCPConnectionStarvation() throws Exception {
//        config();
//        this.transferProperties();
//        this.tDatasource.getConnection().close();
//        javax.sql.DataSource datasource = this.tDatasource;
//        Connection con1 = datasource.getConnection();
//        Connection con2 = null;
//        try {
//            con2 = datasource.getConnection();
//            try {
//                con2.setCatalog("mysql");//make sure connection is valid
//            }catch (SQLException x) {
//                Assert.assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
//            }
//            Assert.assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
//        }catch (Exception x) {
//            Assert.assertFalse("Connection got starved:"+x.getMessage(),true);
//        }finally {
//            if (con2!=null) con2.close();
//        }
//    }

    @Test
    public void testConnectionStarvation() throws Exception {
        config();
        Connection con1 = datasource.getConnection();
        Connection con2 = null;
        try {
            con2 = datasource.getConnection();
            try {
                con2.setCatalog("mysql");//make sure connection is valid
            }catch (SQLException x) {
                Assert.assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
            }
            Assert.assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
        }catch (Exception x) {
            Assert.assertFalse("Connection got starved:"+x.getMessage(),true);
        }finally {
            if (con2!=null) con2.close();
        }
        con1.close();
    }

    @Test
    public void testFairConnectionStarvation() throws Exception {
        init();
        config();
        datasource.getPoolProperties().setFairQueue(true);
        Connection con1 = datasource.getConnection();
        Connection con2 = null;
        try {
            con2 = datasource.getConnection();
            try {
                con2.setCatalog("mysql");//make sure connection is valid
            }catch (SQLException x) {
                Assert.assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
            }
            Assert.assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
        }catch (Exception x) {
            Assert.assertFalse("Connection got starved:"+x.getMessage(),true);
        }finally {
            if (con2!=null) con2.close();
        }
        con1.close();
    }
}
