You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2011/10/17 16:53:13 UTC

svn commit: r1185228 - in /jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core: ConcurrentImportTest.java ConsistencyCheck.java TestHelper.java persistence/AutoFixCorruptNode.java

Author: reschke
Date: Mon Oct 17 14:53:13 2011
New Revision: 1185228

URL: http://svn.apache.org/viewvc?rev=1185228&view=rev
Log:
JCR-3105: add test case for breaking and fixing version storage (also add hook for running consistency check in "fix" mode)

Modified:
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConsistencyCheck.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java?rev=1185228&r1=1185227&r2=1185228&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java Mon Oct 17 14:53:13 2011
@@ -215,7 +215,7 @@ public class ConcurrentImportTest extend
 
     private void checkConsistency() throws RepositoryException {
         try {
-            ConsistencyReport rep = TestHelper.checkConsistency(testRootNode.getSession());
+            ConsistencyReport rep = TestHelper.checkConsistency(testRootNode.getSession(), false);
             assertEquals("Found broken nodes in repository: " + rep, 0, rep.getItems().size());
         } catch (NotExecutableException ex) {
             // ignore

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConsistencyCheck.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConsistencyCheck.java?rev=1185228&r1=1185227&r2=1185228&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConsistencyCheck.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConsistencyCheck.java Mon Oct 17 14:53:13 2011
@@ -40,12 +40,12 @@ public class ConsistencyCheck extends Ab
                 + getHelper().getRepository());
 
         ConsistencyReport rep = TestHelper.checkConsistency(testRootNode
-                .getSession());
+                .getSession(), false);
         assertEquals("Found broken nodes in repository: " + rep, 0, rep
                 .getItems().size());
 
         rep = TestHelper
-                .checkVersionStoreConsistency(testRootNode.getSession());
+                .checkVersionStoreConsistency(testRootNode.getSession(), false);
         assertEquals("Found broken nodes in version storage: " + rep, 0, rep
                 .getItems().size());
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java?rev=1185228&r1=1185227&r2=1185228&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java Mon Oct 17 14:53:13 2011
@@ -47,13 +47,14 @@ public class TestHelper {
      * Runs a consistency check on the workspace used by the specified session.
      *
      * @param session the Session accessing the workspace to be checked
+     * @param runFix whether to attempt fixup
      * @throws RepositoryException if an error occurs while getting the
      * workspace with the given name.
      * @throws NotExecutableException if the {@link PersistenceManager} does
      * not implement {@link ConsistencyChecker}, or if the associated
      * {@link Repository} is not a {@link RepositoryImpl}.
      */
-    public static ConsistencyReport checkConsistency(Session session)
+    public static ConsistencyReport checkConsistency(Session session, boolean runFix)
             throws NotExecutableException, RepositoryException {
         Repository r = session.getRepository();
         if (!(r instanceof RepositoryImpl)) {
@@ -65,7 +66,7 @@ public class TestHelper {
             if (!(pm instanceof ConsistencyChecker)) {
                 throw new NotExecutableException();
             } else {
-                return ((ConsistencyChecker) pm).check(null, true, false);
+                return ((ConsistencyChecker) pm).check(null, true, runFix);
             }
         }
     }
@@ -74,12 +75,13 @@ public class TestHelper {
      * Runs a consistency check on the versioning store used by the specified session.
      *
      * @param session the Session accessing the workspace to be checked
+     * @param runFix whether to attempt fixup
      * @throws RepositoryException
      * @throws NotExecutableException if the {@link PersistenceManager} does
      * not implement {@link ConsistencyChecker}, or if the associated
      * {@link Repository} is not a {@link RepositoryImpl}.
      */
-    public static ConsistencyReport checkVersionStoreConsistency(Session session)
+    public static ConsistencyReport checkVersionStoreConsistency(Session session, boolean runFix)
             throws NotExecutableException, RepositoryException {
         Repository r = session.getRepository();
         if (!(r instanceof RepositoryImpl)) {
@@ -91,7 +93,7 @@ public class TestHelper {
             if (!(pm instanceof ConsistencyChecker)) {
                 throw new NotExecutableException();
             } else {
-                return ((ConsistencyChecker) pm).check(null, true, false);
+                return ((ConsistencyChecker) pm).check(null, true, runFix);
             }
         }
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java?rev=1185228&r1=1185227&r2=1185228&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java Mon Oct 17 14:53:13 2011
@@ -20,8 +20,10 @@ import java.io.File;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
+import java.sql.SQLException;
 import java.util.UUID;
 
+import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.Repository;
@@ -70,19 +72,11 @@ public class AutoFixCorruptNode extends 
         s.save();
         s.logout();
 
-        // remove the bundle for /test/missing directly in the database
-        Connection conn = DriverManager.getConnection("jdbc:derby:" + TEST_DIR
-                + "/workspaces/default/db");
-        PreparedStatement prep = conn
-                .prepareStatement("delete from DEFAULT_BUNDLE  where NODE_ID_HI=? and NODE_ID_LO=?");
-        prep.setLong(1, id.getMostSignificantBits());
-        prep.setLong(2, id.getLeastSignificantBits());
-        prep.executeUpdate();
-        conn.close();
+        destroyBundle(id, "workspaces/default");
 
         s = openSession(rep, false);
         try {
-            ConsistencyReport r = TestHelper.checkConsistency(s);
+            ConsistencyReport r = TestHelper.checkConsistency(s, false);
             assertNotNull(r);
             assertNotNull(r.getItems());
             assertEquals(1, r.getItems().size());
@@ -93,7 +87,117 @@ public class AutoFixCorruptNode extends 
             rep.shutdown();
             FileUtils.deleteDirectory(new File("repository"));
         }
+    }
+
+    public void testMissingVHR() throws Exception {
+
+        // new repository
+        TransientRepository rep = new TransientRepository(new File(TEST_DIR));
+        Session s = openSession(rep, false);
+
+        String oldVersionRecoveryProp = System
+                .getProperty("org.apache.jackrabbit.version.recovery");
+
+        try {
+            Node root = s.getRootNode();
+
+            // add nodes /test and /test/missing
+            Node test = root.addNode("test");
+            test.addMixin("mix:versionable");
+
+            s.save();
+
+            Node vhr = s.getWorkspace().getVersionManager()
+                    .getVersionHistory(test.getPath());
+
+            assertNotNull(vhr);
+
+            Node brokenNode = vhr;
+            String vhrRootVersionId = vhr.getNode("jcr:rootVersion").getIdentifier();
+            
+            UUID destroy = UUID.fromString(brokenNode.getIdentifier());
+            s.logout();
+            
+            destroyBundle(destroy, "version");
+
+            s = openSession(rep, false);
 
+            ConsistencyReport report = TestHelper.checkVersionStoreConsistency(s, false);
+            assertTrue("Report should have reported broken nodes", !report.getItems().isEmpty());
+            
+            try {
+                test = s.getRootNode().getNode("test");
+                vhr = s.getWorkspace().getVersionManager()
+                        .getVersionHistory(test.getPath());
+                fail("should not get here");
+            } catch (Exception ex) {
+                // expected
+            }
+
+            s.logout();
+
+            System.setProperty("org.apache.jackrabbit.version.recovery", "true");
+
+            s = openSession(rep, false);
+
+            test = s.getRootNode().getNode("test");
+            // versioning should be disabled now
+            assertFalse(test.isNodeType("mix:versionable"));
+            
+            try {
+                // try to enable versioning again
+                test.addMixin("mix:versionable");
+                s.save();
+                
+                fail("enabling versioning succeeded unexpectedly");
+            }
+            catch (Exception e) {
+                // we expect this to fail
+            }
+            
+            s.logout();
+            
+            // now redo after running fixup on versioning storage
+            s = openSession(rep, false);
+
+            report = TestHelper.checkVersionStoreConsistency(s, true);
+            assertTrue("Report should have reported broken nodes", !report.getItems().isEmpty());
+            int reportitems = report.getItems().size();
+            
+            // problems should now be fixed
+            report = TestHelper.checkVersionStoreConsistency(s, false);
+            assertTrue("Some problems should have been fixed but are not: " + report, report.getItems().size() < reportitems);
+            
+            test = s.getRootNode().getNode("test");
+            // versioning should be disabled now
+            assertFalse(test.isNodeType("mix:versionable"));
+            
+            // try to enable versioning again
+            test.addMixin("mix:versionable");
+            s.save();
+            
+            Node oldRootVersion = s.getNodeByIdentifier(vhrRootVersionId);
+            try {
+                String path = oldRootVersion.getPath();
+                fail("got path " + path + " for a node believed to be orphaned");
+            }
+            catch (ItemNotFoundException ex) {
+                // orphaned
+            }
+            
+            Node newRootVersion = s.getWorkspace().getVersionManager()
+                    .getVersionHistory(test.getPath()).getRootVersion();
+            assertFalse(
+                    "new root version should be a different node than the one destroyed by the test case",
+                    newRootVersion.getIdentifier().equals(vhrRootVersionId));
+            assertNotNull("new root version should have a intact path",
+                    newRootVersion.getPath());
+        } finally {
+            s.logout();
+            System.setProperty("org.apache.jackrabbit.version.recovery",
+                    oldVersionRecoveryProp == null ? ""
+                            : oldVersionRecoveryProp);
+        }
     }
 
     public void testAutoFix() throws Exception {
@@ -111,15 +215,7 @@ public class AutoFixCorruptNode extends 
         s.save();
         s.logout();
 
-        // remove the bundle for /test/missing directly in the database
-        Connection conn = DriverManager.getConnection("jdbc:derby:" + TEST_DIR
-                + "/workspaces/default/db");
-        PreparedStatement prep = conn
-                .prepareStatement("delete from DEFAULT_BUNDLE  where NODE_ID_HI=? and NODE_ID_LO=?");
-        prep.setLong(1, id.getMostSignificantBits());
-        prep.setLong(2, id.getLeastSignificantBits());
-        prep.executeUpdate();
-        conn.close();
+        destroyBundle(id, "workspaces/default");
 
         // login and try the operation
         s = openSession(rep, false);
@@ -155,7 +251,18 @@ public class AutoFixCorruptNode extends 
         rep.shutdown();
 
         FileUtils.deleteDirectory(new File("repository"));
+    }
 
+    private void destroyBundle(UUID id, String where) throws SQLException {
+        Connection conn = DriverManager.getConnection("jdbc:derby:" + TEST_DIR
+                + "/" + where + "/db");
+        String table = where.equals("version") ? "VERSION_BUNDLE" : "DEFAULT_BUNDLE";
+        PreparedStatement prep = conn.prepareStatement("delete from " + table
+                + " where NODE_ID_HI=? and NODE_ID_LO=?");
+        prep.setLong(1, id.getMostSignificantBits());
+        prep.setLong(2, id.getLeastSignificantBits());
+        prep.executeUpdate();
+        conn.close();
     }
 
     private Session openSession(Repository rep, boolean autoFix)
@@ -168,5 +275,4 @@ public class AutoFixCorruptNode extends 
         }
         return rep.login(cred);
     }
-
 }