package egovframework.rte.fdl.idgnr; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.math.BigDecimal; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import egovframework.rte.fdl.cmmn.exception.FdlException; import javax.annotation.Resource; import javax.sql.DataSource; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.jdbc.JdbcTestUtils; /** * SequenceId Generation Service Test 클래스 * @author 실행환경 개발팀 김태호 * @since 2009.02.01 * @version 1.0 * @see <pre> * == 개정이력(Modification Information) == * * 수정일 수정자 수정내용 * ------- -------- --------------------------- * 2009.02.01 김태호 최초 생성 * * </pre> */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath*:/spring/context-common.xml", "classpath*:/spring/context-sequenceid.xml" }) public class EgovSequenceIdGnrServiceTest extends AbstractJUnit4SpringContextTests { private static final Logger LOGGER = LoggerFactory.getLogger(EgovSequenceIdGnrServiceTest.class); @Resource(name = "Ids-TestSequenceNonExistingSequenceName") private EgovIdGnrService idsTestSequenceNonExistingSequenceName; @Resource(name = "Ids-TestSequenceSimpleRequestIdsSize1") private EgovIdGnrService idsTestSequenceSimpleRequestIdsSize1; @Resource(name = "Ids-TestSequenceMaxByteIds") private EgovIdGnrService idsTestSequenceMaxByteIds; @Resource(name = "Ids-TestSequenceMaxBigDecimalIds") private EgovIdGnrService idsTestSequenceMaxBigDecimalIds; @Resource(name = "dataSource") private DataSource dataSource; @Resource(name = "schemaProperties") Properties schemaProperties; /** * 시퀀스 테이블의 생성 * @throws Exception * fail to initialize */ @Before public void onSetUp() throws Exception { JdbcTestUtils.executeSqlScript(new JdbcTemplate(dataSource), new ClassPathResource("testdata/" + schemaProperties.getProperty("seq_sample_create")), true); } @After public void onTearDown() throws Exception { JdbcTestUtils.executeSqlScript(new JdbcTemplate(dataSource), new ClassPathResource("testdata/" + schemaProperties.getProperty("seq_sample_drop")), true); } /** * 존재하지 않는 시퀀스 테이블에 의한 처리 시 에러나는 것을 확인하는 테스트 */ @Test public void testNonExistingSequenceName() throws Exception { try { // 1. get next integer id idsTestSequenceNonExistingSequenceName.getNextIntegerId(); fail("Should not have gotten an id"); } catch (Exception e) { assertTrue(e instanceof FdlException); } } /** * Integer Type 아이디 생성 테스트 * @throws Exception * fail to test */ @Test public void testSimpleRequestIdsSize1() throws Exception { LOGGER.debug("testSequenceSimpleRequestIdsSize1"); int testCount = 100; // 1. Initialize the counter in the database. initializeNextLongId("idstest", 1); // 2. get next integer id until 99 for (int i = 1; i <= testCount; i++) { int id = idsTestSequenceSimpleRequestIdsSize1.getNextIntegerId(); assertEquals("The returned id was not what was expected.", i, id); } // 3. get next Long id using query directly. assertEquals("The next_id column in the database did not have the expected value.", testCount + 1, peekNextLongId("idstest")); } /** * 다음 Byte Id 읽어오기 테스트 * @throws Exception * fail to test */ @Test public void testSequenceMaxByteIds() throws Exception { int testCount = 100; // max = 127 long max = Byte.MAX_VALUE; long initial = max - testCount; // 1. initialize the counter in the database. initializeNextLongId("idstest", initial); // 2. get next byte id until limitation of Byte for (int i = 0; i <= testCount; i++) { byte id = idsTestSequenceMaxByteIds.getNextByteId(); assertEquals("The returned id was not what was expected.", i + initial, id); } // 3. in case it reached a max value data type // allows, get next byte id. try { byte id = idsTestSequenceMaxByteIds.getNextByteId(); fail("Should not have gotten an id: " + id); } catch (Exception e) { assertTrue(e instanceof FdlException); } } /** * Short Id 읽어오기 테스트 * @throws Exception * fail to test */ @Test public void testMaxShortIds() throws Exception { int testCount = 100; // max is 32767 long max = Short.MAX_VALUE; long initial = max - testCount; // 1. Initialize the counter in the database. initializeNextLongId("idstest", initial); // 2. get next short id until limitation of // Short for (int i = 0; i <= testCount; i++) { short id = idsTestSequenceMaxByteIds.getNextShortId(); assertEquals("The returned id was not what was expected.", i + initial, id); } // 3. in case it reached a max value data type // allows, get next short // id. try { short id = idsTestSequenceMaxByteIds.getNextShortId(); fail("Should not have gotten an id: " + id); } catch (Exception e) { assertTrue(e instanceof FdlException); } } /** * Integer Id 읽어오기 테스트 * @throws Exception * fail to test */ @Test public void testMaxIntegerIds() throws Exception { int testCount = 100; // max is 0x7fffffff long max = Integer.MAX_VALUE; long initial = max - testCount; // 1. Initialize the counter in the database. initializeNextLongId("idstest", initial); // 2. get next integer id until limitation of // Integer for (int i = 0; i <= testCount; i++) { int id = idsTestSequenceMaxByteIds.getNextIntegerId(); assertEquals("The returned id was not what was expected.", i + initial, id); } // 3. in case it reached a max value data type // allows, get next // integer id. try { int id = idsTestSequenceMaxByteIds.getNextIntegerId(); fail("Should not have gotten an id: " + id); } catch (Exception e) { assertTrue(e instanceof FdlException); } } /** * long Id 읽어오기 테스트 * @throws Exception * fail to test */ @Test public void testMaxLongIds() throws Exception { int testCount = 100; // max is 0x7fffffffffffffffL long max = Long.MAX_VALUE; long initial = max - testCount; // 1. Initialize the counter in the database. initializeNextLongId("idstest", initial); // 2. get next long id until limitation of Long for (int i = 0; i <= testCount; i++) { long id = idsTestSequenceMaxByteIds.getNextLongId(); assertEquals("The returned id was not what was expected.", i + initial, id); } // 3. in case it reached a max value data type // allows, get next // long id. try { long id = idsTestSequenceMaxByteIds.getNextLongId(); fail("Should not have gotten an id: " + id); } catch (FdlException e) { assertTrue(e instanceof FdlException); } } /** * BigDecimal Id 읽어오기 테스트 * @throws Exception * fail to test */ @Test public void testBigDecimalIds() throws Exception { int testCount = 100; BigDecimal max = new BigDecimal(Long.MAX_VALUE); BigDecimal initial = max.subtract(new BigDecimal(testCount)); initializeNextBigDecimalId("idstest", initial); for (int i = 0; i <= testCount; i++) { BigDecimal id = idsTestSequenceMaxBigDecimalIds.getNextBigDecimalId(); assertEquals("The returned id was not what was expected.", initial.add(new BigDecimal(i)), id); } assertEquals("The next_id column in the database did not have the expected value.", initial.add(new BigDecimal(testCount + 1)), peekNextBigDecimalId("idstest")); } /** * long Sequence 값 초기화 * @param sequenceName * sequence name * @param nextId * next id */ private void initializeNextLongId(String sequenceName, long nextId) { try { Connection conn = dataSource.getConnection(); try { Statement statement = conn.createStatement(); try { statement.executeUpdate("DROP SEQUENCE " + sequenceName); } catch (SQLException se) { LOGGER.debug("Drop Sequence end."); } statement.executeUpdate("CREATE SEQUENCE " + sequenceName + " MINVALUE " + nextId); } finally { conn.close(); } } catch (Exception e) { fail("Unable to initialize next_id. " + e); } } /** * BigDecimal Sequence 값 초기화 * @param sequenceName * sequence name * @param nextId * next id */ private void initializeNextBigDecimalId(String sequenceName, BigDecimal nextId) { try { Connection conn = dataSource.getConnection(); try { Statement statement = conn.createStatement(); try { statement.executeUpdate("DROP SEQUENCE " + sequenceName); } catch (SQLException se) { LOGGER.debug("Drop Sequence end."); } statement.executeUpdate("CREATE SEQUENCE " + sequenceName + " MINVALUE " + nextId); } finally { conn.close(); } } catch (Exception e) { fail("Unable to initialize next_id. " + e); } } /** * 쿼리를 통해서 long 유형 Id를 읽어와서 테스트에 검증용으로 사용 * @param sequenceName * sequence name * @return next Long Id */ private long peekNextLongId(String sequenceName) { try { Connection conn = dataSource.getConnection(); try { Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery("SELECT " + sequenceName + ".CURRVAL FROM DUAL"); if (rs.next()) { return rs.getLong(1) + 1; } else { fail(sequenceName + " sequence doesn't exist."); return -1; // for compiler } } finally { conn.close(); } } catch (Exception e) { fail("Unable to peek next_id. " + e); return -1; // for compiler } } /** * 쿼리를 통해서 BigDecimal유형 Id를 읽어와서 테스트에 검증용으로 사용 * @param sequenceName * sequence name * @return next BigDecimal Id */ private BigDecimal peekNextBigDecimalId(String sequenceName) { try { Connection conn = dataSource.getConnection(); try { Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery("SELECT " + sequenceName + ".CURRVAL FROM DUAL"); if (rs.next()) { return rs.getBigDecimal(1).add(new BigDecimal(1)); } else { fail(sequenceName + " sequence doesn't exist."); return new BigDecimal(-1); // for // compiler } } finally { conn.close(); } } catch (Exception e) { fail("Unable to peek next_id. " + e); return new BigDecimal(-1); // for compiler } } }