/* * 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 * 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 de.unioninvestment.eai.portal.support.scripting; import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import groovy.lang.Closure; import groovy.lang.GString; import groovy.lang.MissingPropertyException; import java.sql.Connection; import java.sql.SQLException; import java.util.Collection; import java.util.LinkedList; import java.util.List; import org.codehaus.groovy.runtime.GStringImpl; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.springframework.test.context.ContextConfiguration; import com.vaadin.data.Container.Filter; import com.vaadin.data.util.filter.Like; import com.vaadin.data.util.sqlcontainer.ColumnProperty; import com.vaadin.data.util.sqlcontainer.RowId; import com.vaadin.data.util.sqlcontainer.RowItem; import com.vaadin.data.util.sqlcontainer.SQLContainer; import com.vaadin.data.util.sqlcontainer.TemporaryRowId; import com.vaadin.data.util.sqlcontainer.query.OrderBy; import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; import de.unioninvestment.eai.portal.portlet.crud.config.StatementConfig; import de.unioninvestment.eai.portal.portlet.crud.domain.model.DataContainer; import de.unioninvestment.eai.portal.portlet.crud.domain.model.DatabaseContainerRow; import de.unioninvestment.eai.portal.portlet.crud.scripting.database.ExtendedSql; import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptDatabaseContainer; import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptDatabaseModificationsDelegate; import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptRow; import de.unioninvestment.eai.portal.portlet.crud.scripting.model.StatementWrapper; import de.unioninvestment.eai.portal.support.vaadin.junit.AbstractSpringPortletContextTest; import de.unioninvestment.eai.portal.support.vaadin.table.DatabaseQueryDelegate; @ContextConfiguration({ "/eai-portal-web-test-applicationcontext.xml" }) public class ScriptDatabaseModificationsDelegateTest extends AbstractSpringPortletContextTest { private ScriptDatabaseModificationsDelegate scriptDatabaseQueryDelegate; private static final String INSERT_STMT = "INSERT into TestUser values(?, ?)"; private static final String UPDATE_STMT = "UPDATE TestUser set col=? where id=?"; private static final String DELETE_STMT = "DELETE FROM TestUser WHERE id=?"; @Mock private Connection connectionMock; @Mock private ExtendedSql sqlMock; @Mock private SQLContainer containerMock; @Mock private DataContainer databaseContainerMock; @Mock private Closure<Object> insertClosureMock; private StatementWrapper insertStatement; @Mock private Closure<Object> updateClosureMock; private StatementWrapper updateStatement; @Mock private Closure<Object> deleteClosureMock; private StatementWrapper deleteStatement; @Captor private ArgumentCaptor<ScriptRow> rowCaptor; private RowItem newRowItem; private RowItem existingRowItem; @Mock private DatabaseQueryDelegate queryDelegateMock; @Mock private DatabaseContainerRow newRowMock; @Mock private DatabaseContainerRow existingRowMock; @Mock private StatementHelper statementHelperMock; @Mock private RowId rowIdMock; @Before public void setUp() { super.configurePortletUtils(); MockitoAnnotations.initMocks(this); scriptDatabaseQueryDelegate = new ScriptDatabaseModificationsDelegate( databaseContainerMock, queryDelegateMock) { @Override protected ExtendedSql createSingleConnectionSql(Connection conn) { return sqlMock; } }; prepareData(); } private void prepareData() { RowId temporaryId = new TemporaryRowId(1); Collection<ColumnProperty> newColumnProperties = new LinkedList<ColumnProperty>(); newColumnProperties.add(new ColumnProperty("id", true, false, false, false, 1, Integer.class)); newColumnProperties.add(new ColumnProperty("col", false, true, true, false, "Text", String.class)); newRowItem = new RowItem(containerMock, temporaryId, newColumnProperties); when(databaseContainerMock.convertItemToRow(newRowItem, false, true)) .thenReturn(newRowMock); RowId id = new RowId(1); Collection<ColumnProperty> updatedColumnProperties = new LinkedList<ColumnProperty>(); updatedColumnProperties.add(new ColumnProperty("id", true, false, false, false, 1, Integer.class)); updatedColumnProperties.add(new ColumnProperty("col", false, true, true, false, "Text", String.class)); existingRowItem = new RowItem(containerMock, id, updatedColumnProperties); when( databaseContainerMock.convertItemToRow(existingRowItem, false, true)).thenReturn(existingRowMock); insertStatement = new StatementWrapper(insertClosureMock, StatementConfig.Type.SQL); updateStatement = new StatementWrapper(updateClosureMock, StatementConfig.Type.SQL); deleteStatement = new StatementWrapper(deleteClosureMock, StatementConfig.Type.SQL); } @SuppressWarnings("deprecation") @Test public void shouldDelegateGetQueryString() { when(queryDelegateMock.getQueryString(0, 2)).thenReturn("abc"); assertThat(scriptDatabaseQueryDelegate.getQueryString(0, 2), is("abc")); } @Test public void shouldDelegateGetQueryStatement() { when(queryDelegateMock.getQueryStatement(0, 2)).thenReturn( statementHelperMock); assertThat(scriptDatabaseQueryDelegate.getQueryStatement(0, 2), is(statementHelperMock)); } @SuppressWarnings("deprecation") @Test public void shouldDelegateGetCountQuery() { when(queryDelegateMock.getCountQuery()).thenReturn("def"); assertThat(scriptDatabaseQueryDelegate.getCountQuery(), is("def")); } @Test public void shouldDelegateGetCountStatement() { when(queryDelegateMock.getCountStatement()).thenReturn( statementHelperMock); assertThat(scriptDatabaseQueryDelegate.getCountStatement(), is(statementHelperMock)); } @Test public void shouldDelegateGetIndexStatement() { when(queryDelegateMock.getIndexStatement(rowIdMock)).thenReturn( statementHelperMock); assertThat(scriptDatabaseQueryDelegate.getIndexStatement(rowIdMock), is(statementHelperMock)); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowUnsupportedOperationExceptionOnInsertWithoutConfiguredStatement() throws SQLException { scriptDatabaseQueryDelegate.storeRow(connectionMock, newRowItem); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowUnsupportedOperationExceptionOnUpdateWithoutConfiguredStatement() throws SQLException { scriptDatabaseQueryDelegate.storeRow(connectionMock, existingRowItem); } @Test(expected = SQLException.class) public void shouldThrowSqlExceptionOnMissingProperties() throws SQLException { when( insertClosureMock.call(any(ScriptDatabaseContainer.class), any(ScriptRow.class), any(ExtendedSql.class))) .thenThrow(new MissingPropertyException("bla")); scriptDatabaseQueryDelegate = createDelegate(); scriptDatabaseQueryDelegate.storeRow(connectionMock, newRowItem); } @Test(expected = SQLException.class) public void shouldWrapAnyExceptionInAnSqlException() throws SQLException { when( insertClosureMock.call(any(ScriptDatabaseContainer.class), any(ScriptRow.class), any(ExtendedSql.class))) .thenThrow(new RuntimeException("bla")); scriptDatabaseQueryDelegate = createDelegate(); scriptDatabaseQueryDelegate.storeRow(connectionMock, newRowItem); } @Test(expected = SQLException.class) public void shouldThrowSqlExceptionOnInvalidInsertSql() throws SQLException { when(insertClosureMock.call(rowCaptor.capture())).thenReturn( new GStringImpl(new Object[] { 1, "Text" }, new String[] { "INSERT into TestUser values(", ", ", ")" })); when(connectionMock.prepareStatement(Mockito.anyString())).thenThrow( new SQLException("Invalid ExtendedSql")); scriptDatabaseQueryDelegate = createDelegate(); when(connectionMock.prepareStatement(Mockito.anyString())).thenThrow( new SQLException("Invalid SQL")); scriptDatabaseQueryDelegate.storeRow(connectionMock, newRowItem); } @Test public void shouldInsertANewRowWithSql() throws SQLException { GStringImpl insertGString = new GStringImpl(new Object[]{1, "Text"}, INSERT_STMT .split("\\?")); when( insertClosureMock.call(any(ScriptDatabaseContainer.class), rowCaptor.capture(), any(ExtendedSql.class))) .thenReturn(insertGString); when(sqlMock.execute(insertGString)).thenReturn(true); scriptDatabaseQueryDelegate = createDelegate(); int insertCount = scriptDatabaseQueryDelegate.storeRow(connectionMock, newRowItem); assertThat(insertCount, is(1)); } private ScriptDatabaseModificationsDelegate createDelegate() { return new ScriptDatabaseModificationsDelegate( databaseContainerMock, insertStatement, null, null, null, null, queryDelegateMock) { @Override protected ExtendedSql createSingleConnectionSql(Connection conn) { return sqlMock; } }; } @Test public void shouldInsertANewRowWithScript() throws SQLException { when( insertClosureMock.call(any(ScriptDatabaseContainer.class), rowCaptor.capture(), any(ExtendedSql.class))) .thenReturn(1); scriptDatabaseQueryDelegate = new ScriptDatabaseModificationsDelegate( databaseContainerMock, new StatementWrapper(insertClosureMock, StatementConfig.Type.SCRIPT), null, null, null, null, queryDelegateMock); int updateCount = scriptDatabaseQueryDelegate.storeRow(connectionMock, newRowItem); assertThat(updateCount, is(1)); assertThat(rowCaptor.getValue(), notNullValue()); } @Test public void shouldUpdateAnExistingRowWithSql() throws SQLException { when( updateClosureMock.call(any(ScriptDatabaseContainer.class), rowCaptor.capture(), any(ExtendedSql.class))) .thenReturn( new GStringImpl(new Object[] { "Text", 1 }, UPDATE_STMT .split("\\?"))); scriptDatabaseQueryDelegate = new ScriptDatabaseModificationsDelegate( databaseContainerMock, null, updateStatement, null, null, null, queryDelegateMock) { @Override protected ExtendedSql createSingleConnectionSql(Connection conn) { return sqlMock; } }; when(sqlMock.executeUpdate(any(GString.class))).thenReturn(1); int updateCount = scriptDatabaseQueryDelegate.storeRow(connectionMock, existingRowItem); assertThat(updateCount, is(1)); } @Test public void shouldUpdateAnExistingRowWithScript() throws SQLException { when( updateClosureMock.call(any(ScriptDatabaseContainer.class), rowCaptor.capture(), any(ExtendedSql.class))) .thenReturn(1); scriptDatabaseQueryDelegate = new ScriptDatabaseModificationsDelegate( databaseContainerMock, null, new StatementWrapper( updateClosureMock, StatementConfig.Type.SCRIPT), null, null, null, queryDelegateMock); int updateCount = scriptDatabaseQueryDelegate.storeRow(connectionMock, existingRowItem); assertThat(updateCount, is(1)); assertThat(rowCaptor.getValue(), notNullValue()); } @Test public void shouldDeleteAnExistingRowWithSql() throws SQLException { GStringImpl deleteGString = new GStringImpl(new Object[]{1}, DELETE_STMT.split("\\?")); when( deleteClosureMock.call(any(ScriptDatabaseContainer.class),rowCaptor.capture(), any(ExtendedSql.class))).thenReturn( deleteGString); scriptDatabaseQueryDelegate = new ScriptDatabaseModificationsDelegate( databaseContainerMock, null, null, deleteStatement, null, null, queryDelegateMock) { @Override protected ExtendedSql createSingleConnectionSql(Connection conn) { return sqlMock; } }; when(sqlMock.executeUpdate(deleteGString)).thenReturn(1); boolean deleted = scriptDatabaseQueryDelegate.removeRow(connectionMock, existingRowItem); assertThat(deleted, is(true)); } @Test public void shouldDeleteAnExistingRowWithScript() throws SQLException { when( deleteClosureMock.call(any(ScriptDatabaseContainer.class),rowCaptor.capture(), any(ExtendedSql.class))).thenReturn(1); scriptDatabaseQueryDelegate = new ScriptDatabaseModificationsDelegate( databaseContainerMock, null, null, new StatementWrapper( deleteClosureMock, StatementConfig.Type.SCRIPT), null, null, queryDelegateMock); boolean deleted = scriptDatabaseQueryDelegate.removeRow(connectionMock, existingRowItem); assertThat(deleted, is(true)); assertThat(rowCaptor.getValue(), notNullValue()); } @SuppressWarnings("deprecation") @Test public void shouldDelegateGetContainsRowQueryString() { when(queryDelegateMock.getContainsRowQueryString("1", 2)).thenReturn( "def"); assertThat( scriptDatabaseQueryDelegate.getContainsRowQueryString("1", 2), is("def")); } @Test public void shouldDelegateGetContainsRowQueryStatement() throws SQLException { when(queryDelegateMock.getContainsRowQueryStatement("1", 2)) .thenReturn(statementHelperMock); assertThat(scriptDatabaseQueryDelegate.getContainsRowQueryStatement( "1", 2), is(statementHelperMock)); } @Test public void shouldDelegateGetRowByIdStatement() throws SQLException { when(queryDelegateMock.getRowByIdStatement(rowIdMock)).thenReturn( statementHelperMock); assertThat(scriptDatabaseQueryDelegate.getRowByIdStatement(rowIdMock), is(statementHelperMock)); } @Test public void shouldDelegateSetFilters() throws SQLException { List<Filter> filters = asList((Filter)new Like("a", "b")); scriptDatabaseQueryDelegate.setFilters(filters); verify(queryDelegateMock).setFilters(filters); } @Test public void shouldDelegateSetOrderBy() throws SQLException { List<OrderBy> orderBys = asList(new OrderBy("a", true)); scriptDatabaseQueryDelegate.setOrderBy(orderBys); verify(queryDelegateMock).setOrderBy(orderBys); } @Test public void shouldDelegateGetOrderBy() throws SQLException { List<OrderBy> orderBys = asList(new OrderBy("a", true)); when(queryDelegateMock.getOrderBy()).thenReturn(orderBys); assertThat(scriptDatabaseQueryDelegate.getOrderBy(), is(orderBys)); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowUnsupportedOperationExceptionOnRemoveRow() throws SQLException { scriptDatabaseQueryDelegate.removeRow(null, null); } }