content: package com.alibaba.cobar.client;
  
  import static org.testng.AssertJUnit.assertEquals;
  import static org.testng.AssertJUnit.assertNotNull;
  import static org.testng.AssertJUnit.assertNull;
  import static org.testng.AssertJUnit.assertTrue;
  import static org.testng.AssertJUnit.fail;
  
  import java.sql.SQLException;
  import java.util.List;
  
  import org.apache.commons.lang.ArrayUtils;
  import org.springframework.dao.DataAccessException;
  import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
  import org.springframework.orm.ibatis.SqlMapClientCallback;
  import org.testng.annotations.Test;
  
  import com.alibaba.cobar.client.entities.Follower;
  import com.alibaba.cobar.client.entities.Tweet;
  import com.alibaba.cobar.client.support.utils.CollectionUtils;
  import com.ibatis.sqlmap.client.SqlMapExecutor;
  
  @Test(sequential=true)
  public class CobarSqlMapClientTemplateWithNamespaceRouterTest extends AbstractTestNGCobarClientTest {
  
      public CobarSqlMapClientTemplateWithNamespaceRouterTest() {
          super(new String[] { "META-INF/spring/cobar-client-appctx.xml",
                  "META-INF/spring/datasources-appctx.xml",
                  "META-INF/spring/namespace-router-appctx.xml" });
      }
  
      /**
       * since {@link CobarSqlMapClientTemplate#execute(SqlMapClientCallback)},
       * {@link CobarSqlMapClientTemplate#executeWithListResult(SqlMapClientCallback)
       * )} and
       * {@link CobarSqlMapClientTemplate#executeWithMapResult(SqlMapClientCallback)
       * )} don't support partitioning behaviors, we can unit test them together
       * and use one of them as their representation.
       */
      public void testExecutePrefixMethodsOnCobarSqlMapClientTemplate() {
  
          getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
              public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
                  Follower f = new Follower("fname");
                  return executor.insert("com.alibaba.cobar.client.entities.Follower.create", f);
              }
          });
  
          String confirmSQL = "select name from followers where name='fname'";
          // execute method doesn't support partitioning behavior, so the entity will be inserted into default data source, that's , partition1, not partition2 as the rules state.
          verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt1m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
      }
  
      public void testInsertOnCobarSqlMapClientTemplate() {
          Tweet t = new Tweet("tcontent");
          getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Tweet.create", t);
  
          String confirmSQL = "select tweet from tweets where tweet='tcontent'";
  
          verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt1m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
  
          Follower f = new Follower("fname");
           getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f);
  
          confirmSQL = "select name from followers where name='fname'";
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
          verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt2m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
      }
  
      public void testInsertInBatchOnCobarSqlMapClientTemplate() {
          String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
          batchInsertMultipleFollowersAsFixture(names);
  
          for (String name : names) {
              String sql = "select name from followers where name='" + name + "'";
              verifyEntityNonExistenceOnSpecificDataSource(sql, jt1m);
              verifyEntityNonExistenceOnSpecificDataSource(sql, jt1s);
              verifyEntityExistenceOnSpecificDataSource(sql, jt2m);
              verifyEntityNonExistenceOnSpecificDataSource(sql, jt2s);
          }
      }
  
      public void testDeleteOnCobarSqlMapClientTemplate() {
          Follower f = new Follower("fname");
           getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f);
  
          String confirmSQL = "select name from followers where name='fname'";
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
          verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt2m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
  
           getSqlMapClientTemplate().delete("com.alibaba.cobar.client.entities.Follower.deleteByName", f);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
      }
  
      public void testDeleteWithExpectedResultSizeOnCobarSqlMapClientTemplate() {
          Follower f = new Follower("fname");
           getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f);
  
          String confirmSQL = "select name from followers where name='fname'";
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
          verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt2m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
  
          try {
               getSqlMapClientTemplate().delete("com.alibaba.cobar.client.entities.Follower.deleteByName",
                      f, 2);
              fail("only one row will be affected in fact.");
          } catch (DataAccessException e) {
              assertTrue(e instanceof JdbcUpdateAffectedIncorrectNumberOfRowsException);
              JdbcUpdateAffectedIncorrectNumberOfRowsException ex = (JdbcUpdateAffectedIncorrectNumberOfRowsException) e;
              assertEquals(1, ex.getActualRowsAffected());
          }
          // although JdbcUpdateAffectedIncorrectNumberOfRowsException is raised, but the delete does performed successfully.
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
          verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
  
          try {
               getSqlMapClientTemplate().delete("com.alibaba.cobar.client.entities.Follower.deleteByName",
                      f, 0);
          } catch (DataAccessException e) {
              fail();
          }
      }
  
      public void testQueryForListOnCobarSqlMapClientTemplate() {
          // 1. initialize data
          String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
          batchInsertMultipleFollowersAsFixture(names);
  
          // 2. perform assertion
          @SuppressWarnings("unchecked")
          List<Follower> resultList = (List<Follower>) getSqlMapClientTemplate().queryForList(
                  "com.alibaba.cobar.client.entities.Follower.findAll");
          assertTrue(CollectionUtils.isNotEmpty(resultList));
          assertEquals(5, resultList.size());
          for (Follower f : resultList) {
              assertTrue(ArrayUtils.contains(names, f.getName()));
          }
  
          // 3. perform assertion with another different query
          @SuppressWarnings("unchecked")
          List<Follower> followersWithNameStartsWithA = (List<Follower>) getSqlMapClientTemplate()
                  .queryForList("com.alibaba.cobar.client.entities.Follower.finaByNameAlike", "A");
          assertTrue(CollectionUtils.isNotEmpty(followersWithNameStartsWithA));
          assertEquals(3, followersWithNameStartsWithA.size());
          for (Follower f : followersWithNameStartsWithA) {
              assertTrue(ArrayUtils.contains(names, f.getName()));
          }
      }
  
      public void testQueryForMapOnCobarSqlMapClientTemplate() {
          // TODO low priority
      }
  
      /**
       * although we use queryForObject by querying on name column, but it doesn't
       * mean 'name' column is unique, it's because of the data fixture we set up
       * to use.
       */
      public void testQueryForObjectOnCobarSqlMapClientTemplate() {
          // 1. initialize data
          String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
          batchInsertMultipleFollowersAsFixture(names);
  
          // 2. assertion.
          for (String name : names) {
              Follower follower = (Follower) getSqlMapClientTemplate().queryForObject(
                      "com.alibaba.cobar.client.entities.Follower.finaByName", name);
              assertNotNull(follower);
          }
      }
  
      public void testQueryWithRowHandlerOnCobarSqlMapClientTemplate() {
          // TODO low priority
      }
  
      /**
       * WARNING: don't do stupid things such like below, we do this because we
       * can guarantee the shard id will NOT change. if you want to use cobar
       * client corretly, make sure you are partitioning you databases with shard
       * id that will not be changed once it's created!!!
       */
      public void testUpdateOnCobarSqlMapClientTemplate() {
          String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
          batchInsertMultipleFollowersAsFixture(names);
  
          String nameSuffix = "Wang";
          for (String name : names) {
              Follower follower = (Follower) getSqlMapClientTemplate().queryForObject(
                      "com.alibaba.cobar.client.entities.Follower.finaByName", name);
              assertNotNull(follower);
              follower.setName(follower.getName() + nameSuffix);
              getSqlMapClientTemplate().update("com.alibaba.cobar.client.entities.Follower.update",
                      follower);
  
              Long id = follower.getId();
  
              follower = null;
              follower = (Follower) getSqlMapClientTemplate().queryForObject(
                      "com.alibaba.cobar.client.entities.Follower.finaByName", name);
              assertNull(follower);
  
              follower = (Follower) getSqlMapClientTemplate().queryForObject(
                      "com.alibaba.cobar.client.entities.Follower.load", id);
              assertNotNull(follower);
              assertEquals(name + nameSuffix, follower.getName());
          }
  
      }
  
  }
  