Author: stack
Date: Fri Sep  9 04:51:47 2011
New Revision: 1167002

URL: http://svn.apache.org/viewvc?rev=1167002&view=rev
Log:
HBASE-4313 Refactor TestHBaseFsck to make adding individual hbck tests easier

Modified:
    hbase/branches/0.90/CHANGES.txt
    
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java

Modified: hbase/branches/0.90/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/CHANGES.txt?rev=1167002&r1=1167001&r2=1167002&view=diff
==============================================================================
--- hbase/branches/0.90/CHANGES.txt (original)
+++ hbase/branches/0.90/CHANGES.txt Fri Sep  9 04:51:47 2011
@@ -42,6 +42,8 @@ Release 0.90.5 - Unreleased
                META/ROOT regions (todd)
    HBASE-4323  Add debug logging when AssignmentManager can't make a plan
                for a region (todd)
+   HBASE-4313  Refactor TestHBaseFsck to make adding individual hbck tests
+               easier (Jonathan Hsieh)
  
 Release 0.90.4 - August 10, 2011
   BUG FIXES

Modified: 
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java?rev=1167002&r1=1167001&r2=1167002&view=diff
==============================================================================
--- 
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java
 (original)
+++ 
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java
 Fri Sep  9 04:51:47 2011
@@ -19,110 +19,70 @@
  */
 package org.apache.hadoop.hbase.util;
 
-import static org.apache.hadoop.hbase.util.HBaseFsck.ErrorReporter.ERROR_CODE;
-import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hbase.*;
-import org.apache.hadoop.hbase.client.*;
-import org.apache.hadoop.hbase.ipc.HRegionInterface;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.util.HBaseFsck.ErrorReporter.ERROR_CODE;
+import org.apache.zookeeper.KeeperException;
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-
+/**
+ * This tests HBaseFsck's ability to detect reasons for inconsistent tables.
+ */
 public class TestHBaseFsck {
-
   final Log LOG = LogFactory.getLog(getClass());
-  private final static HBaseTestingUtility TEST_UTIL =
-      new HBaseTestingUtility();
+  private final static HBaseTestingUtility TEST_UTIL = new 
HBaseTestingUtility();
   private final static Configuration conf = TEST_UTIL.getConfiguration();
-  private final static byte[] TABLE = Bytes.toBytes("table");
   private final static byte[] FAM = Bytes.toBytes("fam");
 
+  // for the instance, reset every test run
+  private HTable tbl;
+
   @BeforeClass
   public static void setUpBeforeClass() throws Exception {
     TEST_UTIL.startMiniCluster(3);
   }
 
-  private List doFsck(boolean fix) throws Exception {
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    TEST_UTIL.shutdownMiniCluster();
+  }
+
+  private List<ERROR_CODE> doFsck(boolean fix) throws Exception {
     HBaseFsck fsck = new HBaseFsck(conf);
-    fsck.displayFullReport();  // i.e. -details
+    fsck.displayFullReport(); // i.e. -details
     fsck.setTimeLag(0);
     fsck.setFixErrors(fix);
     fsck.doWork();
     return fsck.getErrors().getErrorList();
   }
 
-  private void assertNoErrors(List errs) throws Exception {
+  private void assertNoErrors(List<ERROR_CODE> errs) throws Exception {
     assertEquals(0, errs.size());
   }
 
-  private void assertErrors(List errs, ERROR_CODE[] expectedErrors) {
+  private void assertErrors(List<ERROR_CODE> errs, ERROR_CODE[] 
expectedErrors) {
     assertEquals(Arrays.asList(expectedErrors), errs);
   }
 
-  @Test
-  public void testHBaseFsck() throws Exception {
-    assertNoErrors(doFsck(false));
-
-    TEST_UTIL.createTable(TABLE, FAM);
-
-    // We created 1 table, should be fine
-    assertNoErrors(doFsck(false));
-
-    // Now let's mess it up and change the assignment in .META. to
-    // point to a different region server
-    HTable meta = new HTable(conf, HTableDescriptor.META_TABLEDESC.getName());
-    ResultScanner scanner = meta.getScanner(new Scan());
-
-    resforloop:
-    for (Result res : scanner) {
-      long startCode = Bytes.toLong(res.getValue(HConstants.CATALOG_FAMILY,
-          HConstants.STARTCODE_QUALIFIER));
-
-      for (JVMClusterUtil.RegionServerThread rs :
-          TEST_UTIL.getHBaseCluster().getRegionServerThreads()) {
-
-        HServerInfo hsi = rs.getRegionServer().getServerInfo();
-
-        // When we find a diff RS, change the assignment and break
-        if (startCode != hsi.getStartCode()) {
-          Put put = new Put(res.getRow());
-          put.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
-              Bytes.toBytes(hsi.getHostnamePort()));
-          put.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
-              Bytes.toBytes(hsi.getStartCode()));
-          meta.put(put);
-          break resforloop;
-        }
-      }
-    }
-
-    // Try to fix the data
-    assertErrors(doFsck(true), new ERROR_CODE[]{
-        ERROR_CODE.SERVER_DOES_NOT_MATCH_META});
-    Thread.sleep(15000);
-
-    // Should be fixed now
-    assertNoErrors(doFsck(false));
-
-    // comment needed - what is the purpose of this line
-    new HTable(conf, TABLE).getScanner(new Scan());
-  }
-
-  private HRegionInfo createRegion(Configuration conf, final HTableDescriptor
-      htd, byte[] startKey, byte[] endKey)
+  private HRegionInfo createRegion(Configuration conf,
+      final HTableDescriptor htd, byte[] startKey, byte[] endKey)
       throws IOException {
     HTable meta = new HTable(conf, HConstants.META_TABLE_NAME);
     HRegionInfo hri = new HRegionInfo(htd, startKey, endKey);
@@ -133,67 +93,123 @@ public class TestHBaseFsck {
     return hri;
   }
 
-  @Test
   /**
-   * Tests for inconsistencies in the META data (duplicate start keys, or 
holes)
+   * Setup a clean table before we start mucking with it.
+   * 
+   * @throws IOException
+   * @throws InterruptedException
+   * @throws KeeperException
    */
-  public void testHBaseFsckMeta() throws Exception {
-    assertNoErrors(doFsck(false));
+  void setupTable(String tablename) throws Exception {
+    byte[][] startKeys = new byte[][] { Bytes.toBytes("A"), Bytes.toBytes("B"),
+        Bytes.toBytes("C") };
+    HTableDescriptor desc = new HTableDescriptor(tablename);
+    HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toString(FAM));
+    desc.addFamily(hcd); // If a table has no CF's it doesn't get checked
+    TEST_UTIL.getHBaseAdmin().createTable(desc, startKeys);
+    tbl = new HTable(TEST_UTIL.getConfiguration(), tablename);
+  }
 
-    HTable tbl = TEST_UTIL.createTable(Bytes.toBytes("table2"), FAM);
+  /**
+   * delete table in preparation for next test
+   * 
+   * @param tablename
+   * @throws IOException
+   */
+  void deleteTable(String tablename) throws IOException {
+    HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
+    byte[] tbytes = Bytes.toBytes(tablename);
+    admin.disableTable(tbytes);
+    admin.deleteTable(tbytes);
+  }
 
-    HRegionInfo hriOrig = tbl.getRegionsInfo().keySet().iterator().next();
-    HServerAddress rsAddressOrig = tbl.getRegionsInfo().get(hriOrig);
 
-    byte[][] startKeys = new byte[][]{
-        HConstants.EMPTY_BYTE_ARRAY,
-        Bytes.toBytes("A"),
-        Bytes.toBytes("B"),
-        Bytes.toBytes("C")
-    };
-    TEST_UTIL.createMultiRegions(conf, tbl, FAM, startKeys);
-    Path rootDir = new Path(conf.get(HConstants.HBASE_DIR));
-    FileSystem fs = rootDir.getFileSystem(conf);
-    Path p = new Path(rootDir + "/table2", hriOrig.getEncodedName());
-    fs.delete(p, true);
-
-    Thread.sleep(1 * 1000);
-    ArrayList servers = new ArrayList();
-    servers.add(rsAddressOrig);
-    HBaseFsckRepair.fixDupeAssignment(conf, hriOrig, servers);
+  
+  /**
+   * This creates a clean table and confirms that the table is clean.
+   */
+  @Test
+  public void testHBaseFsckClean() throws Exception {
+    assertNoErrors(doFsck(false));
+    String table = "tableClean";
+    try {
+      setupTable(table);
+
+      // We created 1 table, should be fine
+      assertNoErrors(doFsck(false));
+    } finally {
+      deleteTable(table);
+    }
+  }
 
-    // We created 1 table, should be fine
+  /**
+   * This creates a bad table with regions that have a duplicate start key
+   */
+  @Test
+  public void testDupeStartKey() throws Exception {
     assertNoErrors(doFsck(false));
+    String table = "tableDupeStartKey";
+    try {
+      setupTable(table);
+      assertNoErrors(doFsck(false));
+
+      // Now let's mess it up, by adding a region with a duplicate startkey
+      HRegionInfo hriDupe = createRegion(conf, tbl.getTableDescriptor(),
+          Bytes.toBytes("A"), Bytes.toBytes("A2"));
+      TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriDupe);
+      TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
+          .waitForAssignment(hriDupe);
+
+      assertErrors(doFsck(false),
+          new ERROR_CODE[] { ERROR_CODE.DUPE_STARTKEYS });
+    } finally {
+      deleteTable(table);
+    }
+  }
 
-    // Now let's mess it up, by adding a region with a duplicate startkey
-    HRegionInfo hriDupe = createRegion(conf, tbl.getTableDescriptor(),
-        Bytes.toBytes("A"), Bytes.toBytes("A2"));
-    TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriDupe);
-    TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
-        .waitForAssignment(hriDupe);
-    assertErrors(doFsck(false), new ERROR_CODE[]{ERROR_CODE.DUPE_STARTKEYS});
-
-    // Mess it up by creating an overlap in the metadata
-    HRegionInfo hriOverlap = createRegion(conf, tbl.getTableDescriptor(),
-        Bytes.toBytes("A2"), Bytes.toBytes("B2"));
-    TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriOverlap);
-    TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
-        .waitForAssignment(hriOverlap);
-    assertErrors(doFsck(false), new ERROR_CODE[]{
-        ERROR_CODE.DUPE_STARTKEYS, ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
-        ERROR_CODE.OVERLAP_IN_REGION_CHAIN});
-
-    // Mess it up by leaving a hole in the meta data
-    HRegionInfo hriHole = createRegion(conf, tbl.getTableDescriptor(),
-        Bytes.toBytes("D"), Bytes.toBytes("E"));
-    TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriHole);
-    TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
-        .waitForAssignment(hriHole);
-//    assertError(doFsck(false), ERROR_CODE.OVERLAP_IN_REGION_CHAIN);
-    assertErrors(doFsck(false), new ERROR_CODE[]{ ERROR_CODE.DUPE_STARTKEYS,
-        ERROR_CODE.OVERLAP_IN_REGION_CHAIN, ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
-        ERROR_CODE.HOLE_IN_REGION_CHAIN });
+  /**
+   * This creates a bad table where a start key contained in another region.
+   */
+  @Test
+  public void testCoveredStartKey() throws Exception {
+    String table = "tableCoveredStartKey";
+    try {
+      setupTable(table);
+
+      // Mess it up by creating an overlap in the metadata
+      HRegionInfo hriOverlap = createRegion(conf, tbl.getTableDescriptor(),
+          Bytes.toBytes("A2"), Bytes.toBytes("B2"));
+      TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriOverlap);
+      TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
+          .waitForAssignment(hriOverlap);
+      assertErrors(doFsck(false), new ERROR_CODE[] {
+          ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
+          ERROR_CODE.OVERLAP_IN_REGION_CHAIN });
+    } finally {
+      deleteTable(table);
+    }
+  }
 
+  /**
+   * This creates a bad table with a hole in meta.
+   */
+  @Test
+  public void testMetaHole() throws Exception {
+    String table = "tableMetaHole";
+    try {
+      setupTable(table);
+
+      // Mess it up by leaving a hole in the meta data
+      HRegionInfo hriHole = createRegion(conf, tbl.getTableDescriptor(),
+          Bytes.toBytes("D"), Bytes.toBytes("E"));
+      TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriHole);
+      TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
+          .waitForAssignment(hriHole);
+      assertErrors(doFsck(false),
+          new ERROR_CODE[] { ERROR_CODE.HOLE_IN_REGION_CHAIN });
+    } finally {
+      deleteTable(table);
+    }
   }
 
 }


Reply via email to