/*
 * 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.felix.karaf.main;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public abstract class BaseJDBCLockTest {
    
    DefaultJDBCLock lock;
    Properties props;
    String user = "root";
    String password = "";
    String driver;
    String url;
    String tableName = "LOCK_TABLE";
    String clustername = "karaf_cluster";
    int timeout = 10;
    String momentDatatype = "BIGINT";
    String nodeDatatype = "VARCHAR(20)";
    String createTableStmtSuffix = "";
    
    Connection connection;
    DatabaseMetaData metaData;
    ResultSet resultSet;
    PreparedStatement preparedStatement;
    Statement statement;
    
    abstract DefaultJDBCLock createLock(Properties props);
    
    @BeforeClass
    public static void setUpTestSuite() {
        Properties properties = new Properties();
        properties.put("karaf.bootstrap.log", "target/karaf.log");
        BootstrapLogManager.setProperties(properties);        
    }
    
    @Before
    public void setUp() throws Exception {
        connection = EasyMock.createMock(Connection.class);
        metaData = EasyMock.createMock(DatabaseMetaData.class);
        resultSet = EasyMock.createMock(ResultSet.class);
        preparedStatement = EasyMock.createMock(PreparedStatement.class);
        statement = EasyMock.createMock(Statement.class);
        
        props = new Properties();
        props.put("karaf.lock.jdbc.url", url);
        props.put("karaf.lock.jdbc.driver", driver);
        props.put("karaf.lock.jdbc.user", user);
        props.put("karaf.lock.jdbc.password", password);
        props.put("karaf.lock.jdbc.table", tableName);
        props.put("karaf.lock.jdbc.clustername", clustername);
        props.put("karaf.lock.jdbc.timeout", timeout);
    }
    
    @Test
    public void initShouldCreateTheSchemaIfItNotExists() throws Exception {
        expect(connection.isClosed()).andReturn(false);
        connection.setAutoCommit(false);
        expect(connection.getMetaData()).andReturn(metaData);
        expect(metaData.getTables((String) isNull(), (String) isNull(), eq("LOCK_TABLE"), aryEq(new String[] {"TABLE"}))).andReturn(resultSet);
        expect(resultSet.next()).andReturn(false);
        resultSet.close();
        expect(connection.isClosed()).andReturn(false);
        expect(connection.createStatement()).andReturn(statement);
        expect(statement.execute("CREATE TABLE " + tableName + " (MOMENT " + momentDatatype + ", NODE " + nodeDatatype + ")" + createTableStmtSuffix)).andReturn(false);
        expect(statement.execute("INSERT INTO " + tableName + " (MOMENT, NODE) VALUES (1, '" + clustername + "')")).andReturn(false);
        statement.close();
        connection.commit();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        lock = createLock(props);
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
    }
    
    @Test
    public void initShouldNotCreateTheSchemaIfItAlreadyExists() throws Exception {
        connection.setAutoCommit(false);
        expect(connection.getMetaData()).andReturn(metaData);
        expect(metaData.getTables((String) isNull(), (String) isNull(), eq("LOCK_TABLE"), aryEq(new String[] {"TABLE"}))).andReturn(resultSet);
        expect(resultSet.next()).andReturn(true);
        resultSet.close();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        lock = createLock(props);
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
    }
    
    @Test
    public void lockShouldReturnTrueItTheTableIsNotLocked() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("SELECT * FROM " + tableName + " FOR UPDATE")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.execute()).andReturn(true);
        preparedStatement.close();
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("UPDATE " + tableName + " SET MOMENT = 1")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.executeUpdate()).andReturn(1);
        preparedStatement.close();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        boolean lockAquired = lock.lock();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
        assertTrue(lockAquired);
    }
    
    @Test
    public void lockShouldReturnFalseIfAnotherRowIsLocked() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("SELECT * FROM " + tableName + " FOR UPDATE")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.execute()).andReturn(true);
        preparedStatement.close();
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("UPDATE " + tableName + " SET MOMENT = 1")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.executeUpdate()).andThrow(new SQLException());
        preparedStatement.close();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        boolean lockAquired = lock.lock();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
        assertFalse(lockAquired);
    }
    
    @Test
    public void lockShouldReturnFalseIfTheRowIsAlreadyLocked() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("SELECT * FROM " + tableName + " FOR UPDATE")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.execute()).andReturn(true);
        preparedStatement.close();
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("UPDATE " + tableName + " SET MOMENT = 1")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.executeUpdate()).andThrow(new SQLException());
        preparedStatement.close();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        boolean lockAquired = lock.lock();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
        assertFalse(lockAquired);
    }
    
    @Test
    public void release() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(false);
        expect(connection.isClosed()).andReturn(false);
        expect(connection.isClosed()).andReturn(false);
        connection.rollback();
        connection.close();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        lock.release();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
    }
    
    @Test
    public void releaseShouldSucceedForAnAlreadyClosedConnection() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(true);
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        lock.release();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
    }
    
    @Test
    public void releaseShouldSucceedForANullConnectionReference() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        lock.lockConnection = null;
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        lock.release();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
    }
    
    @Test
    public void isAliveShouldReturnTrueIfItHoldsTheLock() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(false);
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("UPDATE " + tableName + " SET MOMENT = 1")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.executeUpdate()).andReturn(1);
        preparedStatement.close();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        boolean alive = lock.isAlive();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
        assertTrue(alive);
    }
    
    @Test
    public void isAliveShouldReturnFalseIfTheConnectionIsClosed() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(true);
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        boolean alive = lock.isAlive();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
        assertFalse(alive);
    }
    
    @Test
    public void isAliveShouldReturnFalseIfTheConnectionIsNull() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        lock.lockConnection = null;
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        boolean alive = lock.isAlive();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
        assertFalse(alive);
    }
    
    @Test
    public void isAliveShouldReturnFalseIfItNotHoldsTheLock() throws Exception {
        initShouldNotCreateTheSchemaIfItAlreadyExists();
        reset(connection, metaData, statement, preparedStatement, resultSet);
        
        expect(connection.isClosed()).andReturn(false);
        expect(connection.isClosed()).andReturn(false);
        expect(connection.prepareStatement("UPDATE " + tableName + " SET MOMENT = 1")).andReturn(preparedStatement);
        preparedStatement.setQueryTimeout(10);
        expect(preparedStatement.executeUpdate()).andThrow(new SQLException());
        preparedStatement.close();
        
        replay(connection, metaData, statement, preparedStatement, resultSet);
        
        boolean alive = lock.isAlive();
        
        verify(connection, metaData, statement, preparedStatement, resultSet);
        assertFalse(alive);
    }
}