001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.data.platform;
017
018import org.apache.commons.lang.StringUtils;
019import org.junit.After;
020import org.junit.Before;
021import org.junit.Test;
022import org.junit.runner.RunWith;
023import org.kuali.rice.core.api.config.property.Config;
024import org.kuali.rice.core.api.config.property.ConfigContext;
025import org.kuali.rice.core.framework.config.property.SimpleConfig;
026import org.mockito.Mock;
027import org.mockito.runners.MockitoJUnitRunner;
028import org.springframework.dao.DataAccessException;
029import org.springframework.jdbc.support.incrementer.AbstractColumnMaxValueIncrementer;
030import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer;
031import org.springframework.jdbc.support.incrementer.AbstractSequenceMaxValueIncrementer;
032import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
033import org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer;
034
035import javax.sql.DataSource;
036import java.io.IOException;
037import java.sql.Connection;
038import java.sql.DatabaseMetaData;
039import java.sql.SQLException;
040import java.util.Map;
041import java.util.Properties;
042
043import static org.junit.Assert.*;
044import static org.mockito.Mockito.mock;
045import static org.mockito.Mockito.when;
046
047/**
048 * Unit test for {@link MaxValueIncrementerFactory}.
049 *
050 * @author Kuali Rice Team (rice.collab@kuali.org)
051 */
052@RunWith(MockitoJUnitRunner.class)
053public class MaxValueIncrementerFactoryTest {
054
055    @Mock private DataSource mysql;
056    @Mock private DataSource oracle;
057    @Mock private DataSource bad;
058
059    @Before
060    public void setUp() throws Exception {
061        setUpMetaData(mysql, DatabasePlatforms.MYSQL, 5);
062        setUpMetaData(oracle, DatabasePlatforms.ORACLE, 11);
063        setUpMetaData(bad, "BAD!!!!!", 1);
064    }
065
066    private void setUpMetaData(DataSource dataSource, String platformName, int version) throws SQLException {
067        DatabaseMetaData metaData = mock(DatabaseMetaData.class);
068        when(metaData.getDatabaseProductName()).thenReturn(platformName);
069        when(metaData.getDatabaseMajorVersion()).thenReturn(version);
070        Connection connection = mock(Connection.class);
071        when(connection.getMetaData()).thenReturn(metaData);
072        when(dataSource.getConnection()).thenReturn(connection);
073    }
074
075
076    @Test
077    public void testGetIncrementer_Oracle() throws Exception {
078        DataFieldMaxValueIncrementer incrementer = MaxValueIncrementerFactory.getIncrementer(oracle, "MY_SEQUENCE");
079        assertTrue(incrementer instanceof OracleSequenceMaxValueIncrementer);
080        OracleSequenceMaxValueIncrementer oracleIncrementer = (OracleSequenceMaxValueIncrementer)incrementer;
081        assertEquals("MY_SEQUENCE", oracleIncrementer.getIncrementerName());
082
083        // ensure that it's caching the incrementer
084        assertSame(incrementer, MaxValueIncrementerFactory.getIncrementer(oracle, "MY_SEQUENCE"));
085        // ensure that different sequence gives a different incrementer
086        assertNotSame(incrementer, MaxValueIncrementerFactory.getIncrementer(oracle, "MY_SEQUENCE_2"));
087
088    }
089
090    @Test
091    public void testGetIncrementer_MySQL() throws Exception {
092        DataFieldMaxValueIncrementer incrementer = MaxValueIncrementerFactory.getIncrementer(mysql, "MY_SEQUENCE");
093        assertTrue(incrementer instanceof MaxValueIncrementerFactory.EnhancedMySQLMaxValueIncrementer);
094        MaxValueIncrementerFactory.EnhancedMySQLMaxValueIncrementer mysqlIncrementer =
095                (MaxValueIncrementerFactory.EnhancedMySQLMaxValueIncrementer)incrementer;
096        assertEquals("MY_SEQUENCE", mysqlIncrementer.getIncrementerName());
097        assertEquals("ID", mysqlIncrementer.getColumnName());
098
099        // ensure that it's caching the incrementer
100        assertSame(incrementer, MaxValueIncrementerFactory.getIncrementer(mysql, "MY_SEQUENCE"));
101        // ensure that different sequence gives a different incrementer
102        assertNotSame(incrementer, MaxValueIncrementerFactory.getIncrementer(mysql, "MY_SEQUENCE_2"));
103
104    }
105
106    @Test(expected = UnsupportedDatabasePlatformException.class)
107    public void testGetIncrementer_Bad() throws Exception {
108        MaxValueIncrementerFactory.getIncrementer(bad, "MY_SEQUENCE");
109    }
110
111    @Test
112    public void testGetIncrementer_CaseInsensitive() throws Exception {
113        DataFieldMaxValueIncrementer incrementer1 = MaxValueIncrementerFactory.getIncrementer(mysql, "MY_SEQUENCE");
114        DataFieldMaxValueIncrementer incrementer2 = MaxValueIncrementerFactory.getIncrementer(mysql, "MY_sequence");
115        DataFieldMaxValueIncrementer incrementer3 = MaxValueIncrementerFactory.getIncrementer(mysql, "my_sequence");
116        assertSame(incrementer1, incrementer2);
117        assertSame(incrementer2, incrementer3);
118    }
119
120    @Test
121    public void testGetIncrementer_CacheByDataSource() throws Exception {
122        DataFieldMaxValueIncrementer incrementer1 = MaxValueIncrementerFactory.getIncrementer(mysql, "MY_SEQUENCE");
123        DataFieldMaxValueIncrementer incrementer2 = MaxValueIncrementerFactory.getIncrementer(oracle, "MY_SEQUENCE");
124        assertNotSame(incrementer1, incrementer2);
125    }
126
127    @Test(expected = IllegalArgumentException.class)
128    public void testGetIncrementer_NullDataSource() throws Exception {
129        MaxValueIncrementerFactory.getIncrementer(null, "MY_SEQUENCE");
130    }
131
132    @Test(expected = IllegalArgumentException.class)
133    public void testGetIncrementer_NullIncrementerName() throws Exception {
134        MaxValueIncrementerFactory.getIncrementer(mysql, null);
135    }
136
137    @Test(expected = IllegalArgumentException.class)
138    public void testGetIncrementer_BlankIncrementerName() throws Exception {
139        MaxValueIncrementerFactory.getIncrementer(mysql, "");
140    }
141
142    @Test
143    public void testCustomIncrementerDatasourceVersion() throws Exception {
144        SimpleConfig config = new SimpleConfig();
145        config.putProperty("rice.krad.data.platform.incrementer.mysql.5",
146                "org.kuali.rice.krad.data.platform.testincrementers.CustomIncrementerMySQLVersion5");
147        config.putProperty("rice.krad.data.platform.incrementer.oracle.11",
148                "org.kuali.rice.krad.data.platform.testincrementers.CustomIncrementerOracleVersion11");
149        ConfigContext.init(config);
150
151        DataFieldMaxValueIncrementer mySQLMaxVal = MaxValueIncrementerFactory.getIncrementer(mysql,"test_mySQL");
152        assertTrue("Found MySQL custom incrementer",mySQLMaxVal != null);
153        assertTrue("Custom incrementer for MySQL should be mySQL5 for String val",
154                        StringUtils.equals(mySQLMaxVal.nextStringValue(),"mySQL5"));
155
156        DataFieldMaxValueIncrementer oracleMaxVal = MaxValueIncrementerFactory.getIncrementer(oracle,"test_oracle");
157        assertTrue("Found Oracle custom incrementer", oracleMaxVal != null);
158    }
159
160    @Test
161    public void testCustomIncrementerDatasourceNoVersion() throws Exception {
162        SimpleConfig config = new SimpleConfig();
163        config.putProperty("rice.krad.data.platform.incrementer.mysql",
164                "org.kuali.rice.krad.data.platform.testincrementers.CustomIncrementerMySQLVersion5");
165        config.putProperty("rice.krad.data.platform.incrementer.oracle",
166                "org.kuali.rice.krad.data.platform.testincrementers.CustomIncrementerOracleVersion11");
167        ConfigContext.init(config);
168
169        DataFieldMaxValueIncrementer mySQLMaxVal = MaxValueIncrementerFactory.getIncrementer(mysql,"test_mySQL");
170        assertTrue("Found MySQL custom incrementer",mySQLMaxVal != null);
171        assertTrue("Custom incrementer for MySQL should be mySQL5 for String val",
172                StringUtils.equals(mySQLMaxVal.nextStringValue(),"mySQL5"));
173
174        DataFieldMaxValueIncrementer oracleMaxVal = MaxValueIncrementerFactory.getIncrementer(oracle,"test_oracle");
175        assertTrue("Found Oracle custom incrementer", oracleMaxVal != null);
176    }
177
178    @Test(expected = InstantiationError.class)
179    public void testCustomIncrementerDatasourceInvalidClass() throws Exception {
180        SimpleConfig config = new SimpleConfig();
181        config.putProperty("rice.krad.data.platform.incrementer.mysql",
182                "org.kuali.rice.krad.data.platform.testincrementers.NonExistent");
183        ConfigContext.init(config);
184
185        DataFieldMaxValueIncrementer mySQLMaxVal = MaxValueIncrementerFactory.getIncrementer(mysql,"test_mySQL");
186        assertTrue("Cannot create incrementer", mySQLMaxVal == null);
187    }
188
189    @After
190    public void clearContext(){
191        ConfigContext.destroy();
192    }
193}