summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Winkler2009-02-24 10:36:19 (EST)
committerStefan Winkler2009-02-24 10:36:19 (EST)
commitccddadb675107d30690ca410140ae669d73d43a5 (patch)
treee1ec5f06bd061f6b31853ec49ed0be95c545a38b
parent8e8fc26b98d1fda1a941ed675223e7546fd06b79 (diff)
downloadcdo-ccddadb675107d30690ca410140ae669d73d43a5.zip
cdo-ccddadb675107d30690ca410140ae669d73d43a5.tar.gz
cdo-ccddadb675107d30690ca410140ae669d73d43a5.tar.bz2
[262914] [DB] Provide DBStore integrity regression testcases
https://bugs.eclipse.org/bugs/show_bug.cgi?id=262914
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AbstractDBStoreVerifier.java203
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/AuditDBStoreIntegrityVerifier.java190
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/store/verifier/NonAuditDBStoreIntegrityVerifier.java184
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 0000000..790fa65
--- /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 0000000..6ad9101
--- /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 0000000..40fb092
--- /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();
+ }
+ }
+}