Package com.jolbox.bonecp

Source Code of com.jolbox.bonecp.TestStatementCache

/**
*  Copyright 2010 Wallace Wadge
*
*    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 com.jolbox.bonecp;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentMap;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;

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


/** Test class for statement cache
* @author wwadge
*
*/
@SuppressWarnings("deprecation")
public class TestStatementCache {
  /** Mock handle. */
  private IStatementCache mockCache;
  /** Mock handle. */
  private Logger mockLogger;
  /** Config clone. */
  private BoneCPConfig config;
  /** Mock handle. */
  private MockJDBCDriver driver;

  /** Mock setup.
   * @throws ClassNotFoundException
   * @throws SQLException
   */
  @BeforeClass
  public static void setup() throws ClassNotFoundException, SQLException{
  }

  /**
   * Init.
   * @throws SQLException
   */
 
  @Before
  public void beforeTest() throws SQLException{
    driver = new MockJDBCDriver(new MockJDBCAnswer() {
     
      public Connection answer() throws SQLException {
        return new MockConnection();
      }
    });
    mockCache = createNiceMock(IStatementCache.class);
    mockLogger = createNiceMock(Logger.class);
    config = CommonTestUtils.getConfigClone();
    config.setJdbcUrl(CommonTestUtils.url);
    config.setUsername(CommonTestUtils.username);
    config.setPassword(CommonTestUtils.password);
    config.setIdleConnectionTestPeriodInMinutes(0);
    config.setIdleMaxAgeInMinutes(0);
    config.setStatementsCacheSize(0);
    config.setReleaseHelperThreads(0);
    config.setDisableConnectionTracking(true);
    config.setStatementReleaseHelperThreads(0);
    config.setStatisticsEnabled(true);
  }

  /** After cleanup.
   * @throws SQLException
   */
  @After
  public void teardown() throws SQLException{
    driver.disable();
  }
 
 
  /** Prepared statement tests.
   * @throws SQLException
   * @throws SecurityException
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   */
  @Test
  public void testPreparedStatement() throws SQLException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
    BoneCP dsb = null ;
    CommonTestUtils.logTestInfo("Tests that prepared statements are obtained from cache when set.");
    config.setMinConnectionsPerPartition(10);
    config.setMaxConnectionsPerPartition(20);
    config.setAcquireIncrement(5);
    config.setPartitionCount(1);
    config.setStatementsCacheSize(1);
    config.setLogStatementsEnabled(true);
    config.setStatementReleaseHelperThreads(0);
    dsb = new BoneCP(config);

    ConnectionHandle con = (ConnectionHandle) dsb.getConnection();
    Field preparedStatement = con.getClass().getDeclaredField("preparedStatementCache");
    preparedStatement.setAccessible(true);
    // switch to our mock
    preparedStatement.set(con, mockCache);
    expect(mockCache.get(isA(String.class))).andReturn(null);
//    mockCache.put(isA(String.class), isA(PreparedStatement.class));

    replay(mockCache);
    Statement statement = con.prepareStatement(CommonTestUtils.TEST_QUERY);
    statement.close();
    verify(mockCache);

    reset(mockCache);
    expect(mockCache.get(isA(String.class))).andReturn(null);
    replay(mockCache);

    con.prepareStatement(CommonTestUtils.TEST_QUERY);
    statement.close();
    verify(mockCache);
    dsb.shutdown();
    statement.close();
    con.close();
    dsb.close();
    CommonTestUtils.logPass();
  }

  /** Test case for when item is not in cache.
   * @throws SQLException
   * @throws SecurityException
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   */
  @Test
  public void testStatementCacheNotInCache() throws SQLException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
    CommonTestUtils.logTestInfo("Tests statement not in cache.");

    StatementCache cache = new StatementCache(5, false, null);
    assertNull(cache.get("nonExistent"));

    CommonTestUtils.logPass();
  }

  /** Test case method for calling different get signatures.
   * @throws SQLException
   * @throws SecurityException
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   */
  @Test
  public void testStatementCacheDifferentGetSignatures() throws SQLException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
    CommonTestUtils.logTestInfo("Tests statement get() signatures.");

    CommonTestUtils.logTestInfo("Tests statement close (put in cache).");
    String sql = CommonTestUtils.TEST_QUERY;
    BoneCP dsb = null ;
    config.setMinConnectionsPerPartition(1);
    config.setMaxConnectionsPerPartition(5);
    config.setAcquireIncrement(1);
    config.setPartitionCount(1);
    config.setStatementsCacheSize(5);
    config.setStatementReleaseHelperThreads(0);
    dsb = new BoneCP(config);
    Connection conn = dsb.getConnection();
    Statement statement = conn.prepareStatement(sql);
    statement.close();

   
    StatementCache cache = new StatementCache(5, false, null);
    cache.putIfAbsent("test1", (StatementHandle)statement);
    assertNotNull(cache.get("test1"));
   
    assertNull(cache.get("test1", 1));
    assertNull(cache.get("test1", new int[]{1}));
    assertNull(cache.get("test1", new String[]{"1"}));
    assertNull(cache.get("test1", 1, 1));
    assertNull(cache.get("test1", 1, 1, 1));
    dsb.close();
    CommonTestUtils.logPass();
  }
 
  /** Test case for cache put.
   * @throws SQLException
   * @throws SecurityException
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   */
  @Test
  public void testStatementCachePut() throws SQLException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
    CommonTestUtils.logTestInfo("Tests statement close (put in cache).");
    String sql = CommonTestUtils.TEST_QUERY;
    BoneCP dsb = null ;
    config.setMinConnectionsPerPartition(1);
    config.setMaxConnectionsPerPartition(5);
    config.setAcquireIncrement(1);
    config.setPartitionCount(1);
    config.setStatementsCacheSize(5);
    config.setStatementReleaseHelperThreads(0);
    config.setStatisticsEnabled(true);
    dsb = new BoneCP(config);
    Connection conn = dsb.getConnection();
    Statement statement = conn.prepareStatement(sql);
    statement.close();
    Field statementCache = conn.getClass().getDeclaredField("preparedStatementCache");
    statementCache.setAccessible(true);
    IStatementCache cache = (IStatementCache) statementCache.get(conn);
   
    statement = cache.get(sql);
    assertNotNull(statement);
    // Calling again should not provide the same object
    assertNull(cache.get(sql));

    // now pretend we have 1 connection being asked for the same statement
    // twice
    statement = conn.prepareStatement(sql);
    Statement statement2 = conn.prepareStatement(sql);

    statement.close(); // release it again
    statement2.close(); // release the other one

    statement2.close();
    statement.close();
    conn.close();
    dsb.shutdown();
   
    dsb.close();
   
    CommonTestUtils.logPass();
  }

  /** Test limits.
   * @throws SQLException
   * @throws SecurityException
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   */
  @Test
  public void testStatementCacheLimits() throws SQLException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
    CommonTestUtils.logTestInfo("Tests statement caching module.");
    String sql = CommonTestUtils.TEST_QUERY;
    BoneCP dsb = null ;
    config.setMinConnectionsPerPartition(2);
    config.setMaxConnectionsPerPartition(5);
    config.setAcquireIncrement(1);
    config.setPartitionCount(1);
    config.setStatementsCacheSize(5);
    dsb = new BoneCP(config);
    Connection conn = dsb.getConnection();
    StatementHandle statement = (StatementHandle)conn.prepareStatement(sql);

    StatementCache cache = new StatementCache(5, true, new Statistics(dsb));
    cache.putIfAbsent("test1", statement);
    cache.putIfAbsent("test2", statement);
    cache.putIfAbsent("test3", statement);
    cache.putIfAbsent("test4", statement);
    cache.putIfAbsent("test5", statement);


    conn.close();

    for (int i=0; i < 5000000; i++){
      cache.putIfAbsent("test"+i, statement);
      if ((i % 10000) == 0){
        System.gc();
      }
      if (cache.size() != i) {
        break;
      }
    }
    // some elements should have been dropped in the cache
    assertFalse(cache.size()==5000000);
 

    dsb.shutdown();
    CommonTestUtils.logPass();
  }

 
  /** Tests statement cache clear.
   * @throws SecurityException
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws SQLException
   */
  @SuppressWarnings({ "unchecked", "rawtypes" })
  @Test
  public void testStatementCacheClear() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, SQLException {
    ConcurrentMap mockCache = createNiceMock(ConcurrentMap.class);
    List<StatementHandle> mockStatementCollections = createNiceMock(List.class);
    StatementCache testClass = new StatementCache(1, false, null);
    Field field = testClass.getClass().getDeclaredField("cache");
    field.setAccessible(true);
    field.set(testClass, mockCache);
   
    Iterator<StatementHandle> mockIterator = createNiceMock(Iterator.class);
    StatementHandle mockStatement = createNiceMock(StatementHandle.class);
   
    expect(mockCache.values()).andReturn(mockStatementCollections).anyTimes();
    expect(mockStatementCollections.iterator()).andReturn(mockIterator).anyTimes();
    expect(mockIterator.hasNext()).andReturn(true).times(2).andReturn(false).once();
    expect(mockIterator.next()).andReturn(mockStatement).anyTimes();
    mockStatement.close();
    expectLastCall().once().andThrow(new SQLException()).once();
   
    mockCache.clear();
    expectLastCall().once();
    replay(mockCache, mockStatementCollections, mockIterator,mockStatement);
   
    testClass.clear();
    verify(mockCache, mockStatement);
   
  }

  /** Proper closure test
   * @throws SecurityException
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws SQLException
   */
  @SuppressWarnings({ "unchecked", "rawtypes" })
  @Test
  public void testStatementCacheCheckForProperClosure() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, SQLException {
   
    ConcurrentMap mockCache = createNiceMock(ConcurrentMap.class);
    List<StatementHandle> mockStatementCollections = createNiceMock(List.class);
    StatementCache testClass = new StatementCache(1, false, null);
    Field field = testClass.getClass().getDeclaredField("cache");
    field.setAccessible(true);
    field.set(testClass, mockCache);

    field = testClass.getClass().getDeclaredField("logger");
    TestUtils.setFinalStatic(field, mockLogger);

    Iterator<StatementHandle> mockIterator = createNiceMock(Iterator.class);
    StatementHandle mockStatement = createNiceMock(StatementHandle.class);
   
    expect(mockCache.values()).andReturn(mockStatementCollections).anyTimes();
    expect(mockStatementCollections.iterator()).andReturn(mockIterator).anyTimes();
    expect(mockIterator.hasNext()).andReturn(true).once().andReturn(false).once();
    expect(mockIterator.next()).andReturn(mockStatement).anyTimes();
    expect(mockStatement.isClosed()).andReturn(false).once();

    mockLogger.error((String)anyObject());
    expectLastCall().once();
    replay(mockCache, mockStatementCollections, mockIterator,mockStatement, mockLogger);
   
    testClass.checkForProperClosure();
    verify(mockCache, mockStatement, mockLogger);
   
  }

}
TOP

Related Classes of com.jolbox.bonecp.TestStatementCache

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.