diff options
3 files changed, 577 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AbstractDBStoreVerifier.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AbstractDBStoreVerifier.java new file mode 100644 index 0000000000..790fa65733 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AbstractDBStoreVerifier.java @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2004 - 2009 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stefan Winkler - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.store.verifier; + +import static junit.framework.Assert.assertTrue; + +import org.eclipse.emf.cdo.common.model.CDOClass; +import org.eclipse.emf.cdo.common.model.CDOPackage; +import org.eclipse.emf.cdo.server.IRepository; +import org.eclipse.emf.cdo.server.db.IClassMapping; +import org.eclipse.emf.cdo.server.db.IDBStore; +import org.eclipse.emf.cdo.server.db.IDBStoreAccessor; +import org.eclipse.emf.cdo.tests.bundle.OM; + +import org.eclipse.net4j.util.om.trace.ContextTracer; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Stefan Winkler + */ +public abstract class AbstractDBStoreVerifier +{ + protected static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractDBStoreVerifier.class); + + private IRepository repository; + + private IDBStoreAccessor accessor = null; + + public AbstractDBStoreVerifier(IRepository repository) + { + this.repository = repository; + assertTrue(repository.getStore() instanceof IDBStore); + } + + protected IRepository getRepository() + { + return repository; + } + + protected IDBStore getStore() + { + return (IDBStore)repository.getStore(); + } + + protected Statement getStatement() + { + if (accessor == null) + { + accessor = (IDBStoreAccessor)repository.getStore().getReader(null); + } + + return accessor.getJDBCDelegate().getStatement(); + } + + protected List<IClassMapping> getClassMappings() + { + ArrayList<IClassMapping> result = new ArrayList<IClassMapping>(); + for (CDOPackage pkg : repository.getPackageManager().getPackages()) + { + // CDO core package is not mapped in horizontal mapping + if (pkg.equals(repository.getPackageManager().getCDOCorePackage())) + { + continue; + } + + for (CDOClass cls : pkg.getClasses()) + { + result.add(getStore().getMappingStrategy().getClassMapping(cls)); + } + } + + return result; + } + + protected void cleanUp() + { + if (accessor != null) + { + accessor.release(); + } + } + + public void verify() throws VerificationException + { + try + { + TRACER.format("Starting {0} ...", getClass().getSimpleName()); + doVerify(); + TRACER.format("{0} completed without complaints ...", getClass().getSimpleName()); + + } + catch (Exception e) + { + throw new VerificationException(e); + } + finally + { + cleanUp(); + } + } + + protected void sqlDump(String sql) + { + ResultSet rs = null; + try + { + TRACER.format("Dumping output of {0}", sql); + rs = getStatement().executeQuery(sql); + int numCol = rs.getMetaData().getColumnCount(); + + StringBuilder row = new StringBuilder(); + for (int c = 1; c <= numCol; c++) + { + row.append(String.format("%10s | ", rs.getMetaData().getColumnLabel(c))); + } + + TRACER.trace(row.toString()); + + row = new StringBuilder(); + for (int c = 1; c <= numCol; c++) + { + row.append("-----------+--"); + } + + TRACER.trace(row.toString()); + + while (rs.next()) + { + row = new StringBuilder(); + for (int c = 1; c <= numCol; c++) + { + row.append(String.format("%10s | ", rs.getString(c))); + } + + TRACER.trace(row.toString()); + } + + row = new StringBuilder(); + for (int c = 1; c <= numCol; c++) + { + row.append("-----------+-"); + } + + TRACER.trace(row.toString()); + } + catch (SQLException ex) + { + // NOP + } + finally + { + if (rs != null) + { + try + { + rs.close(); + } + catch (SQLException ex) + { + // NOP + } + } + } + } + + protected abstract void doVerify() throws Exception; + + /** + * @author Stefan Winkler + */ + public static class VerificationException extends RuntimeException + { + private static final long serialVersionUID = 1L; + + public VerificationException(String message) + { + super(message); + } + + public VerificationException(String message, Throwable t) + { + super(message, t); + } + + public VerificationException(Throwable t) + { + super(t); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AuditDBStoreIntegrityVerifier.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AuditDBStoreIntegrityVerifier.java new file mode 100644 index 0000000000..6ad910159b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AuditDBStoreIntegrityVerifier.java @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2004 - 2009 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stefan Winkler - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.store.verifier; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import org.eclipse.emf.cdo.server.IRepository; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.db.IClassMapping; +import org.eclipse.emf.cdo.server.db.IReferenceMapping; +import org.eclipse.emf.cdo.server.internal.db.CDODBSchema; +import org.eclipse.emf.cdo.server.internal.db.HorizontalMappingStrategy; + +import org.eclipse.net4j.util.collection.Pair; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.AssertionFailedError; + +/** + * @author Stefan Winkler + */ +public class AuditDBStoreIntegrityVerifier extends AbstractDBStoreVerifier +{ + public AuditDBStoreIntegrityVerifier(IRepository repo) + { + super(repo); + + // this is a verifier for auditing mode + assertTrue(getStore().getRevisionTemporality() == IStore.RevisionTemporality.AUDITING); + // ... and for horizontal class mapping + assertTrue(getStore().getMappingStrategy() instanceof HorizontalMappingStrategy); + } + + @Override + protected void doVerify() throws Exception + { + for (IClassMapping mapping : getClassMappings()) + { + if (mapping != null && mapping.getTable() != null) + { + verifyClassMapping(mapping); + } + } + } + + private void verifyClassMapping(IClassMapping mapping) throws Exception + { + verifyAtMostOneUnrevised(mapping); + verifyUniqueIdVersion(mapping); + verifyReferences(mapping); + } + + private void verifyAtMostOneUnrevised(IClassMapping mapping) throws Exception + { + String tableName = mapping.getTable().getName(); + TRACER.format("verifyAtMostOneUnrevised: {0} ...", tableName); + + String sql = "SELECT " + CDODBSchema.ATTRIBUTES_ID + ", count(1) FROM " + tableName + " WHERE " + + CDODBSchema.ATTRIBUTES_REVISED + "= 0 GROUP BY " + CDODBSchema.ATTRIBUTES_ID; + TRACER.format(" Executing SQL: {0} ", sql); + + ResultSet resultSet = getStatement().executeQuery(sql); + try + { + while (resultSet.next()) + { + assertTrue("Multiple unrevised rows for ID " + resultSet.getLong(1), resultSet.getInt(2) <= 1); + } + } + finally + { + resultSet.close(); + } + } + + /** + * Verify that the pair (id,version) is unique. + */ + private void verifyUniqueIdVersion(IClassMapping mapping) throws Exception + { + String tableName = mapping.getTable().getName(); + TRACER.format("verifyUniqueIdVersion: {0} ...", tableName); + + String sql = "SELECT " + CDODBSchema.ATTRIBUTES_ID + "," + CDODBSchema.ATTRIBUTES_VERSION + ", count(1) FROM " + + tableName + " GROUP BY " + CDODBSchema.ATTRIBUTES_ID + "," + CDODBSchema.ATTRIBUTES_VERSION; + + TRACER.format(" Executing SQL: {0} ", sql); + + ResultSet resultSet = getStatement().executeQuery(sql); + try + { + while (resultSet.next()) + { + assertTrue("Multiple rows for ID " + resultSet.getLong(1) + "v" + resultSet.getInt(2), resultSet.getInt(3) <= 1); + } + } + catch (AssertionFailedError e) + { + TRACER.trace(e.getMessage()); + sqlDump("SELECT * FROM " + tableName + " WHERE " + CDODBSchema.ATTRIBUTES_REVISED + "=0"); + throw e; + } + finally + { + resultSet.close(); + } + } + + private void verifyReferences(IClassMapping mapping) throws Exception + { + List<IReferenceMapping> referenceMappings = mapping.getReferenceMappings(); + if (referenceMappings == null) + { + return; + } + + String tableName = mapping.getTable().getName(); + String sql = "SELECT " + CDODBSchema.ATTRIBUTES_ID + ", " + CDODBSchema.ATTRIBUTES_VERSION + " FROM " + tableName; + + ArrayList<Pair<Long, Integer>> idVersions = new ArrayList<Pair<Long, Integer>>(); + + ResultSet resultSet = getStatement().executeQuery(sql); + try + { + while (resultSet.next()) + { + idVersions.add(new Pair<Long, Integer>(resultSet.getLong(1), resultSet.getInt(2))); + } + } + finally + { + resultSet.close(); + } + + for (IReferenceMapping refMapping : referenceMappings) + { + for (Pair<Long, Integer> idVersion : idVersions) + { + verifyCorrectIndices(refMapping, idVersion.getElement1(), idVersion.getElement2()); + } + } + } + + private void verifyCorrectIndices(IReferenceMapping refMapping, long id, int version) throws Exception + { + String tableName = refMapping.getTable().getName(); + + TRACER.format("verifyUniqueIdVersion: {0} for ID{1}v{2} ...", tableName, id, version); + + String sql = "SELECT " + CDODBSchema.REFERENCES_IDX + " FROM " + tableName + " WHERE " + + CDODBSchema.REFERENCES_SOURCE + "=" + id + " AND " + CDODBSchema.REFERENCES_VERSION + "=" + version + + " ORDER BY " + CDODBSchema.REFERENCES_IDX; + + TRACER.format(" Executing SQL: {0} ", sql); + + ResultSet resultSet = getStatement().executeQuery(sql); + int indexShouldBe = 0; + + try + { + while (resultSet.next()) + { + assertEquals("Index " + indexShouldBe + " missing for ID" + id + "v" + version, indexShouldBe++, resultSet + .getInt(1)); + } + } + catch (AssertionFailedError e) + { + sqlDump("SELECT * FROM " + tableName + " WHERE " + CDODBSchema.REFERENCES_SOURCE + "=" + id + " AND " + + CDODBSchema.REFERENCES_VERSION + "=" + version + " ORDER BY " + CDODBSchema.REFERENCES_IDX); + throw e; + } + finally + { + resultSet.close(); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/NonAuditDBStoreIntegrityVerifier.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/NonAuditDBStoreIntegrityVerifier.java new file mode 100644 index 0000000000..40fb092bad --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/NonAuditDBStoreIntegrityVerifier.java @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2004 - 2009 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stefan Winkler - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.store.verifier; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import org.eclipse.emf.cdo.server.IRepository; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.db.IClassMapping; +import org.eclipse.emf.cdo.server.db.IReferenceMapping; +import org.eclipse.emf.cdo.server.internal.db.CDODBSchema; +import org.eclipse.emf.cdo.server.internal.db.HorizontalMappingStrategy; + +import org.eclipse.net4j.util.collection.Pair; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Stefan Winkler + */ +public class NonAuditDBStoreIntegrityVerifier extends AbstractDBStoreVerifier +{ + public NonAuditDBStoreIntegrityVerifier(IRepository repo) + { + super(repo); + + // this is a verifier for non-auditing mode + assertTrue(getStore().getRevisionTemporality() == IStore.RevisionTemporality.NONE); + // ... and for horizontal class mapping + assertTrue(getStore().getMappingStrategy() instanceof HorizontalMappingStrategy); + } + + @Override + protected void doVerify() throws Exception + { + for (IClassMapping mapping : getClassMappings()) + { + if (mapping != null && mapping.getTable() != null) + { + verifyClassMapping(mapping); + } + } + } + + private void verifyClassMapping(IClassMapping mapping) throws Exception + { + verifyNoUnrevisedRevisions(mapping); + verifyUniqueId(mapping); + verifyReferences(mapping); + } + + /** + * Verify that there is no row with cdo_revised == 0. + */ + private void verifyNoUnrevisedRevisions(IClassMapping mapping) throws Exception + { + String tableName = mapping.getTable().getName(); + String sql = "SELECT count(1) FROM " + tableName + " WHERE " + CDODBSchema.ATTRIBUTES_REVISED + " <> 0"; + ResultSet resultSet = getStatement().executeQuery(sql); + try + { + assertTrue(resultSet.next()); + assertEquals("Revised revision in table " + tableName, 0, resultSet.getInt(1)); + } + finally + { + resultSet.close(); + } + } + + /** + * Verify that the id is unique. + */ + private void verifyUniqueId(IClassMapping mapping) throws Exception + { + String tableName = mapping.getTable().getName(); + String sql = "SELECT " + CDODBSchema.ATTRIBUTES_ID + ", count(1) FROM " + tableName + " GROUP BY " + + CDODBSchema.ATTRIBUTES_ID; + + ResultSet resultSet = getStatement().executeQuery(sql); + + try + { + while (resultSet.next()) + { + assertEquals("Multiple rows for ID " + resultSet.getLong(1), 1, resultSet.getInt(2)); + } + } + finally + { + resultSet.close(); + } + } + + private void verifyReferences(IClassMapping mapping) throws Exception + { + List<IReferenceMapping> referenceMappings = mapping.getReferenceMappings(); + if (referenceMappings == null) + { + return; + } + + String tableName = mapping.getTable().getName(); + String sql = "SELECT " + CDODBSchema.ATTRIBUTES_ID + ", " + CDODBSchema.ATTRIBUTES_VERSION + " FROM " + tableName; + + ArrayList<Pair<Long, Integer>> idVersions = new ArrayList<Pair<Long, Integer>>(); + + ResultSet resultSet = getStatement().executeQuery(sql); + try + { + while (resultSet.next()) + { + idVersions.add(new Pair<Long, Integer>(resultSet.getLong(1), resultSet.getInt(2))); + } + } + finally + { + resultSet.close(); + } + + for (IReferenceMapping refMapping : referenceMappings) + { + for (Pair<Long, Integer> idVersion : idVersions) + { + verifyOnlyLatestReferences(refMapping, idVersion.getElement1(), idVersion.getElement2()); + verifyCorrectIndices(refMapping, idVersion.getElement1()); + } + } + } + + /** + * Verify that no reference with sourceId == ID exist which have another version + */ + private void verifyOnlyLatestReferences(IReferenceMapping refMapping, long id, int version) throws Exception + { + String tableName = refMapping.getTable().getName(); + String sql = "SELECT count(1) FROM " + tableName + " WHERE " + CDODBSchema.REFERENCES_SOURCE + "=" + id + " AND " + + CDODBSchema.REFERENCES_VERSION + "<>" + version; + + ResultSet resultSet = getStatement().executeQuery(sql); + try + { + assertTrue(resultSet.next()); + assertEquals("Table " + tableName + " contains old references for id " + id + "(version should be " + version + + ")", 0, resultSet.getInt(1)); + } + finally + { + resultSet.close(); + } + } + + private void verifyCorrectIndices(IReferenceMapping refMapping, long id) throws Exception + { + String tableName = refMapping.getTable().getName(); + String sql = "SELECT " + CDODBSchema.REFERENCES_IDX + " FROM " + tableName + " WHERE " + + CDODBSchema.REFERENCES_SOURCE + "=" + id + " ORDER BY " + CDODBSchema.REFERENCES_IDX; + + ResultSet resultSet = getStatement().executeQuery(sql); + int indexShouldBe = 0; + try + { + while (resultSet.next()) + { + assertEquals("Index " + indexShouldBe + " missing for ID" + id, indexShouldBe++, resultSet.getInt(1)); + } + } + finally + { + resultSet.close(); + } + } +} |