// 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
// 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 com.cloud.utils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Table;
import javax.sql.DataSource;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

import com.cloud.utils.db.DbUtil;
import com.cloud.utils.db.TransactionLegacy;

@RunWith(MockitoJUnitRunner.class)
public class DbUtilTest {

    @Mock
    Connection connection;

    @Mock
    PreparedStatement preparedStatement;

    @Mock
    Statement statement;

    @Mock
    ResultSet resultSet;

    @Mock
    DataSource dataSource;

    DataSource backup;

    Map<String, Connection> connectionMapBackup = null;

    Map<String, Connection> connectionMap = null;

    @Table(name = "test_table")
    static class Testbean {
        String noAnnotation;
        @Column()
        String withAnnotation;
        @Column(name = "surprise")
        String withAnnotationAndName;
    }

    @Test
    public void getColumnName() throws SecurityException, NoSuchFieldException {
        // if no annotation, then the field name
        Assert.assertEquals("noAnnotation", DbUtil.getColumnName(Testbean.class.getDeclaredField("noAnnotation")));
        // there is annotation with name, take the name
        Assert.assertEquals("surprise", DbUtil.getColumnName(Testbean.class.getDeclaredField("withAnnotationAndName")));
    }

    @Test
    @Ignore
    public void getColumnNameWithAnnotationButWithoutNameAttribute() throws SecurityException, NoSuchFieldException {
        // there is annotation, but no name defined, fallback to field name
        // this does not work this way, it probably should
        Assert.assertEquals("withAnnotation", DbUtil.getColumnName(Testbean.class.getDeclaredField("withAnnotation")));

    }

    static class IsPersistableTestBean {
        static final String staticFinal = "no";
        final String justFinal = "no";
        transient String transientField;
        transient static String strange = "";
        String instanceField;
    }

    @Test
    public void isPersistable() throws SecurityException, NoSuchFieldException {
        Assert.assertFalse(DbUtil.isPersistable(IsPersistableTestBean.class.getDeclaredField("staticFinal")));
        Assert.assertFalse(DbUtil.isPersistable(IsPersistableTestBean.class.getDeclaredField("justFinal")));
        Assert.assertFalse(DbUtil.isPersistable(IsPersistableTestBean.class.getDeclaredField("transientField")));
        Assert.assertFalse(DbUtil.isPersistable(IsPersistableTestBean.class.getDeclaredField("strange")));
        Assert.assertTrue(DbUtil.isPersistable(IsPersistableTestBean.class.getDeclaredField("instanceField")));
    }

    class Bar {

    }

    @Test
    public void getTableName() {
        Assert.assertEquals("test_table", DbUtil.getTableName(Testbean.class));
        Assert.assertEquals("Bar", DbUtil.getTableName(Bar.class));
    }

    @SuppressWarnings("unchecked")
    @Before
    public void setup() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Field globalLocks = DbUtil.class.getDeclaredField("s_connectionForGlobalLocks");
        globalLocks.setAccessible(true);
        connectionMapBackup = (Map<String, Connection>)globalLocks.get(null);
        connectionMap = new HashMap<String, Connection>();
        globalLocks.set(null, connectionMap);

        Field dsField = TransactionLegacy.class.getDeclaredField("s_ds");
        dsField.setAccessible(true);
        backup = (DataSource)dsField.get(null);
        dsField.set(null, dataSource);
    }

    @After
    public void cleanup() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Field globalLocks = DbUtil.class.getDeclaredField("s_connectionForGlobalLocks");
        globalLocks.setAccessible(true);
        globalLocks.set(null, connectionMapBackup);

        Field dsField = TransactionLegacy.class.getDeclaredField("s_ds");
        dsField.setAccessible(true);
        dsField.set(null, backup);
    }

    @Test
    public void getGlobalLock() throws SQLException {
        Mockito.when(dataSource.getConnection()).thenReturn(connection);
        Mockito.when(connection.prepareStatement(Matchers.anyString())).thenReturn(preparedStatement);
        Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
        Mockito.when(resultSet.first()).thenReturn(true);
        Mockito.when(resultSet.getInt(1)).thenReturn(1);
        Assert.assertTrue(DbUtil.getGlobalLock("TEST", 600));

        Mockito.verify(connection).prepareStatement(Matchers.anyString());
        Mockito.verify(preparedStatement).close();
        Mockito.verify(resultSet).close();
    }

    @Test
    public void getGlobalLockTimeout() throws SQLException {
        Mockito.when(dataSource.getConnection()).thenReturn(connection);
        Mockito.when(connection.prepareStatement(Matchers.anyString())).thenReturn(preparedStatement);
        Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
        Mockito.when(resultSet.first()).thenReturn(true);
        Mockito.when(resultSet.getInt(1)).thenReturn(0);
        Assert.assertFalse(DbUtil.getGlobalLock("TEST", 600));

        Mockito.verify(connection).prepareStatement(Matchers.anyString());
        Mockito.verify(preparedStatement).close();
        Mockito.verify(resultSet).close();
        Mockito.verify(connection).close();

        // if any error happens, the connection map must be cleared
        Assert.assertTrue(connectionMap.isEmpty());
    }

    @Test
    public void closeNull() {
        DbUtil.closeStatement((Statement)null);
        DbUtil.closeConnection((Connection)null);
        DbUtil.closeResultSet((ResultSet)null);
        // no exception should be thrown
    }

    @Test
    public void closeConnection() throws IOException, SQLException {
        DbUtil.closeConnection(connection);
        Mockito.verify(connection).close();
    }

    @Test
    public void closeConnectionFail() throws IOException, SQLException {
        Mockito.doThrow(new SQLException("it is all right")).when(connection).close();
        DbUtil.closeConnection(connection);
        Mockito.verify(connection).close();
    }

    @Test
    public void closeStatement() throws IOException, SQLException {
        DbUtil.closeStatement(statement);
        Mockito.verify(statement).close();
    }

    @Test
    public void closeStatementFail() throws IOException, SQLException {
        Mockito.doThrow(new SQLException("it is all right")).when(statement).close();
        DbUtil.closeStatement(statement);
        Mockito.verify(statement).close();
    }

    @Test
    public void closeResultSet() throws IOException, SQLException {
        DbUtil.closeResultSet(resultSet);
        Mockito.verify(resultSet).close();
    }

    @Test
    public void closeResultSetFail() throws IOException, SQLException {
        Mockito.doThrow(new SQLException("it is all right")).when(resultSet).close();
        DbUtil.closeResultSet(resultSet);
        Mockito.verify(resultSet).close();
    }

    @Test
    @Ignore
    //can not be performed since assertion embedded in this branch of execution
        public
        void releaseGlobalLockNotexisting() throws SQLException {
        Assert.assertFalse(DbUtil.releaseGlobalLock("notexisting"));
        Mockito.verify(dataSource, Mockito.never()).getConnection();
    }

    @Test
    public void releaseGlobalLock() throws SQLException {
        Mockito.when(connection.prepareStatement(Matchers.anyString())).thenReturn(preparedStatement);
        Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
        Mockito.when(resultSet.first()).thenReturn(true);
        Mockito.when(resultSet.getInt(1)).thenReturn(1);
        connectionMap.put("testLock", connection);
        Assert.assertTrue(DbUtil.releaseGlobalLock("testLock"));

        Mockito.verify(resultSet).close();
        Mockito.verify(preparedStatement).close();
        Mockito.verify(connection).close();
        Assert.assertFalse(connectionMap.containsKey("testLock"));
    }

}
