/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI 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 org.openengsb.core.edbi.jdbc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.sql.DataSource;
import org.junit.Before;
import org.junit.Test;
import org.openengsb.core.api.model.OpenEngSBModel;
import org.openengsb.core.edbi.api.Index;
import org.openengsb.core.edbi.api.IndexCommit;
import org.openengsb.core.edbi.api.IndexField;
import org.openengsb.core.edbi.api.IndexFieldNameTranslator;
import org.openengsb.core.edbi.api.IndexNameTranslator;
import org.openengsb.core.edbi.jdbc.api.NoSuchTableException;
import org.openengsb.core.edbi.jdbc.api.TableEngine;
import org.openengsb.core.edbi.jdbc.api.TypeMap;
import org.openengsb.core.edbi.jdbc.operation.DeleteOperation;
import org.openengsb.core.edbi.jdbc.operation.InsertOperation;
import org.openengsb.core.edbi.jdbc.operation.UpdateOperation;
import org.openengsb.core.edbi.models.TestModel;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class HistoryTableEngineTest extends AbstractTableEngineTest {
private Connection connection;
@Before
public void setUp() throws Exception {
connection = getDataSource().getConnection();
List<IndexField<?>> fields = testIndex.getFields();
((JdbcIndexField<?>) fields.get(0)).setMappedName("TESTID");
((JdbcIndexField<?>) fields.get(1)).setMappedName("TESTINTEGER");
((JdbcIndexField<?>) fields.get(2)).setMappedName("SUBMODEL");
}
@Override
protected TableEngine createEngine(DataSource dataSource, TypeMap typeMap) {
// Translators (mockito 1.8.5 has a bug with overloading generics)
IndexNameTranslator indexNameTranslatorStub = new IndexNameTranslator() {
@Override
public String translate(Index<?> index) {
return (index == testIndex) ? "HISTORY_TABLE" : null;
}
};
IndexFieldNameTranslator fieldNameTranslatorStub = new IndexFieldNameTranslator() {
@Override
public String translate(IndexField<?> field) {
return field.getName().toUpperCase();
}
};
return new HistoryTableEngine(dataSource, typeMap, indexNameTranslatorStub, fieldNameTranslatorStub);
}
@Test
public void create_works() throws Exception {
engine.create(testIndex);
try (ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM HISTORY_TABLE")) {
ResultSetMetaData metaData = rs.getMetaData();
assertEquals(12, metaData.getColumnCount());
assertEquals("REV_ID", metaData.getColumnName(1));
assertEquals("REV_COMMIT", metaData.getColumnName(2));
assertEquals("REV_TIMESTAMP", metaData.getColumnName(3));
assertEquals("REV_OPERATION", metaData.getColumnName(4));
assertEquals("REV_USER", metaData.getColumnName(5));
assertEquals("REV_CONTEXTID", metaData.getColumnName(6));
assertEquals("REV_DOMAINID", metaData.getColumnName(7));
assertEquals("REV_CONNECTORID", metaData.getColumnName(8));
assertEquals("REV_INSTANCEID", metaData.getColumnName(9));
assertEquals("TESTID", metaData.getColumnName(10));
assertEquals("TESTINTEGER", metaData.getColumnName(11));
assertEquals("SUBMODEL", metaData.getColumnName(12));
}
assertEquals("HISTORY_TABLE", testIndex.getHistoryTableName());
}
@Test
public void drop_works() throws Exception {
long cnt;
String sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ?";
engine.create(testIndex);
cnt = jdbc().queryForLong(sql, "HISTORY_TABLE");
assertEquals(1, cnt);
engine.drop(testIndex);
cnt = jdbc().queryForLong(sql, "HISTORY_TABLE");
assertEquals(0, cnt);
try {
engine.get(testIndex);
fail("Did not throw NoSuchTableException");
} catch (NoSuchTableException e) {
}
}
@Test(expected = NoSuchTableException.class)
public void drop_nonExistingIndex_throwsException() throws Exception {
engine.drop(testIndex);
}
@Test
public void execute_insert_createsRecordsCorrectly() throws Exception {
engine.create(testIndex);
IndexCommit commit = mock(IndexCommit.class);
when(commit.getTimestamp()).thenReturn(new Date(42));
// TODO: mock entire commit
List models = new ArrayList<>();
models.add(new TestModel("A", 42));
models.add(new TestModel("B", -42));
InsertOperation operation = new InsertOperation(commit, testIndex, models);
engine.execute(operation);
try (ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM HISTORY_TABLE")) {
assertTrue(rs.next());
assertEquals("A", rs.getString("TESTID"));
assertEquals(42, rs.getInt("TESTINTEGER"));
assertEquals(1L, rs.getLong("REV_ID"));
assertEquals("INSERT", rs.getString("REV_OPERATION"));
assertEquals(new Date(42), rs.getTimestamp("REV_TIMESTAMP"));
assertTrue(rs.next());
assertEquals("B", rs.getString("TESTID"));
assertEquals(-42, rs.getInt("TESTINTEGER"));
assertEquals(2L, rs.getLong("REV_ID"));
assertEquals("INSERT", rs.getString("REV_OPERATION"));
assertEquals(new Date(42), rs.getTimestamp("REV_TIMESTAMP"));
assertFalse(rs.next());
}
}
@Test
public void execute_update_updatesRecordsCorrectly() throws Exception {
engine.create(testIndex);
IndexCommit commit = mock(IndexCommit.class);
when(commit.getTimestamp()).thenReturn(new Date(42));
TestModel testModelA = new TestModel("A", 42);
TestModel testModelB = new TestModel("B", -42);
List<OpenEngSBModel> list = new ArrayList<>();
list.add((OpenEngSBModel) testModelA);
list.add((OpenEngSBModel) testModelB);
engine.execute(new InsertOperation(commit, testIndex, list));
testModelB.setTestInteger(43);
IndexCommit updateCommit = mock(IndexCommit.class);
when(updateCommit.getTimestamp()).thenReturn(new Date(84));
engine.execute(new UpdateOperation(updateCommit, testIndex, new ArrayList(Arrays.asList(testModelB))));
try (ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM HISTORY_TABLE")) {
assertTrue(rs.next());
assertEquals("A", rs.getString("TESTID"));
assertEquals(42, rs.getInt("TESTINTEGER"));
assertEquals(1L, rs.getLong("REV_ID"));
assertEquals("INSERT", rs.getString("REV_OPERATION"));
assertEquals(new Date(42), rs.getTimestamp("REV_TIMESTAMP"));
assertTrue(rs.next());
assertEquals("B", rs.getString("TESTID"));
assertEquals(-42, rs.getInt("TESTINTEGER"));
assertEquals(2L, rs.getLong("REV_ID"));
assertEquals("INSERT", rs.getString("REV_OPERATION"));
assertEquals(new Date(42), rs.getTimestamp("REV_TIMESTAMP"));
assertTrue(rs.next());
assertEquals("B", rs.getString("TESTID"));
assertEquals(43, rs.getInt("TESTINTEGER"));
assertEquals(3L, rs.getLong("REV_ID"));
assertEquals("UPDATE", rs.getString("REV_OPERATION"));
assertEquals(new Date(84), rs.getTimestamp("REV_TIMESTAMP"));
assertFalse(rs.next());
}
}
@Test
public void execute_delete_deletesRecordsCorrectly() throws Exception {
engine.create(testIndex);
IndexCommit commit = mock(IndexCommit.class);
when(commit.getTimestamp()).thenReturn(new Date(42));
TestModel testModelA = new TestModel("A", 42);
TestModel testModelB = new TestModel("B", -42);
engine.execute(new InsertOperation(commit, testIndex, new ArrayList(Arrays.asList(testModelA, testModelB))));
IndexCommit deleteCommit = mock(IndexCommit.class);
when(deleteCommit.getTimestamp()).thenReturn(new Date(84));
engine.execute(new DeleteOperation(deleteCommit, testIndex, new ArrayList(Arrays.asList(testModelB))));
try (ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM HISTORY_TABLE")) {
assertTrue(rs.next());
assertEquals("A", rs.getString("TESTID"));
assertEquals(42, rs.getInt("TESTINTEGER"));
assertEquals(1L, rs.getLong("REV_ID"));
assertEquals("INSERT", rs.getString("REV_OPERATION"));
assertEquals(new Date(42), rs.getTimestamp("REV_TIMESTAMP"));
assertTrue(rs.next());
assertEquals("B", rs.getString("TESTID"));
assertEquals(-42, rs.getInt("TESTINTEGER"));
assertEquals(2L, rs.getLong("REV_ID"));
assertEquals("INSERT", rs.getString("REV_OPERATION"));
assertEquals(new Date(42), rs.getTimestamp("REV_TIMESTAMP"));
assertTrue(rs.next());
assertEquals("B", rs.getString("TESTID"));
assertEquals(-42, rs.getInt("TESTINTEGER"));
assertEquals(3L, rs.getLong("REV_ID"));
assertEquals("DELETE", rs.getString("REV_OPERATION"));
assertEquals(new Date(84), rs.getTimestamp("REV_TIMESTAMP"));
assertFalse(rs.next());
}
}
}