hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From apurt...@apache.org
Subject svn commit: r945816 [10/11] - in /hadoop/hbase/trunk: ./ contrib/ contrib/stargate/ core/ core/src/main/java/org/apache/hadoop/hbase/rest/ core/src/main/java/org/apache/hadoop/hbase/rest/client/ core/src/main/java/org/apache/hadoop/hbase/rest/metrics/ ...
Date Tue, 18 May 2010 18:49:14 GMT
Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithFilters.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithFilters.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithFilters.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithFilters.java Tue May 18 18:49:12 2010
@@ -0,0 +1,978 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.Delete;
+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.client.Scan;
+import org.apache.hadoop.hbase.filter.BinaryComparator;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
+import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
+import org.apache.hadoop.hbase.filter.PageFilter;
+import org.apache.hadoop.hbase.filter.PrefixFilter;
+import org.apache.hadoop.hbase.filter.QualifierFilter;
+import org.apache.hadoop.hbase.filter.RegexStringComparator;
+import org.apache.hadoop.hbase.filter.RowFilter;
+import org.apache.hadoop.hbase.filter.SkipFilter;
+import org.apache.hadoop.hbase.filter.SubstringComparator;
+import org.apache.hadoop.hbase.filter.ValueFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.FilterList.Operator;
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.rest.client.Cluster;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.apache.hadoop.hbase.rest.model.CellModel;
+import org.apache.hadoop.hbase.rest.model.CellSetModel;
+import org.apache.hadoop.hbase.rest.model.RowModel;
+import org.apache.hadoop.hbase.rest.model.ScannerModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestScannersWithFilters extends HBaseRESTClusterTestBase {
+
+  private static final Log LOG =
+    LogFactory.getLog(TestScannersWithFilters.class);
+
+  private Client client;
+  private JAXBContext context;
+  private Marshaller marshaller;
+  private Unmarshaller unmarshaller;
+
+  private static final byte [][] ROWS_ONE = {
+    Bytes.toBytes("testRowOne-0"), Bytes.toBytes("testRowOne-1"),
+    Bytes.toBytes("testRowOne-2"), Bytes.toBytes("testRowOne-3")
+  };
+
+  private static final byte [][] ROWS_TWO = {
+    Bytes.toBytes("testRowTwo-0"), Bytes.toBytes("testRowTwo-1"),
+    Bytes.toBytes("testRowTwo-2"), Bytes.toBytes("testRowTwo-3")
+  };
+
+  private static final byte [][] FAMILIES = {
+    Bytes.toBytes("testFamilyOne"), Bytes.toBytes("testFamilyTwo")
+  };
+
+  private static final byte [][] QUALIFIERS_ONE = {
+    Bytes.toBytes("testQualifierOne-0"), Bytes.toBytes("testQualifierOne-1"),
+    Bytes.toBytes("testQualifierOne-2"), Bytes.toBytes("testQualifierOne-3")
+  };
+
+  private static final byte [][] QUALIFIERS_TWO = {
+    Bytes.toBytes("testQualifierTwo-0"), Bytes.toBytes("testQualifierTwo-1"),
+    Bytes.toBytes("testQualifierTwo-2"), Bytes.toBytes("testQualifierTwo-3")
+  };
+
+  private static final byte [][] VALUES = {
+    Bytes.toBytes("testValueOne"), Bytes.toBytes("testValueTwo")
+  };
+
+  private long numRows = ROWS_ONE.length + ROWS_TWO.length;
+  private long colsPerRow = FAMILIES.length * QUALIFIERS_ONE.length;
+
+  public TestScannersWithFilters() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(
+        CellModel.class,
+        CellSetModel.class,
+        RowModel.class,
+        ScannerModel.class);
+    marshaller = context.createMarshaller();
+    unmarshaller = context.createUnmarshaller();
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    client = new Client(new Cluster().add("localhost", testServletPort));
+    HBaseAdmin admin = new HBaseAdmin(conf);
+    if (!admin.tableExists(getName())) {
+      HTableDescriptor htd = new HTableDescriptor(getName());
+      htd.addFamily(new HColumnDescriptor(FAMILIES[0]));
+      htd.addFamily(new HColumnDescriptor(FAMILIES[1]));
+      admin.createTable(htd);
+      HTable table = new HTable(conf, getName());
+      // Insert first half
+      for(byte [] ROW : ROWS_ONE) {
+        Put p = new Put(ROW);
+        for(byte [] QUALIFIER : QUALIFIERS_ONE) {
+          p.add(FAMILIES[0], QUALIFIER, VALUES[0]);
+        }
+        table.put(p);
+      }
+      for(byte [] ROW : ROWS_TWO) {
+        Put p = new Put(ROW);
+        for(byte [] QUALIFIER : QUALIFIERS_TWO) {
+          p.add(FAMILIES[1], QUALIFIER, VALUES[1]);
+        }
+        table.put(p);
+      }
+      
+      // Insert second half (reverse families)
+      for(byte [] ROW : ROWS_ONE) {
+        Put p = new Put(ROW);
+        for(byte [] QUALIFIER : QUALIFIERS_ONE) {
+          p.add(FAMILIES[1], QUALIFIER, VALUES[0]);
+        }
+        table.put(p);
+      }
+      for(byte [] ROW : ROWS_TWO) {
+        Put p = new Put(ROW);
+        for(byte [] QUALIFIER : QUALIFIERS_TWO) {
+          p.add(FAMILIES[0], QUALIFIER, VALUES[1]);
+        }
+        table.put(p);
+      }
+      
+      // Delete the second qualifier from all rows and families
+      for(byte [] ROW : ROWS_ONE) {
+        Delete d = new Delete(ROW);
+        d.deleteColumns(FAMILIES[0], QUALIFIERS_ONE[1]);
+        d.deleteColumns(FAMILIES[1], QUALIFIERS_ONE[1]);
+        table.delete(d);
+      }    
+      for(byte [] ROW : ROWS_TWO) {
+        Delete d = new Delete(ROW);
+        d.deleteColumns(FAMILIES[0], QUALIFIERS_TWO[1]);
+        d.deleteColumns(FAMILIES[1], QUALIFIERS_TWO[1]);
+        table.delete(d);
+      }
+      colsPerRow -= 2;
+      
+      // Delete the second rows from both groups, one column at a time
+      for(byte [] QUALIFIER : QUALIFIERS_ONE) {
+        Delete d = new Delete(ROWS_ONE[1]);
+        d.deleteColumns(FAMILIES[0], QUALIFIER);
+        d.deleteColumns(FAMILIES[1], QUALIFIER);
+        table.delete(d);
+      }
+      for(byte [] QUALIFIER : QUALIFIERS_TWO) {
+        Delete d = new Delete(ROWS_TWO[1]);
+        d.deleteColumns(FAMILIES[0], QUALIFIER);
+        d.deleteColumns(FAMILIES[1], QUALIFIER);
+        table.delete(d);
+      }
+      numRows -= 2;
+    }
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    client.shutdown();
+    super.tearDown();
+  }
+
+  private void verifyScan(Scan s, long expectedRows, long expectedKeys) 
+      throws Exception {
+    ScannerModel model = ScannerModel.fromScan(s);
+    model.setBatch(Integer.MAX_VALUE); // fetch it all at once
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(model, writer);
+    LOG.debug(writer.toString());
+    byte[] body = Bytes.toBytes(writer.toString());
+    Response response = client.put("/" + getName() + "/scanner", MIMETYPE_XML,
+      body);
+    assertEquals(response.getCode(), 201);
+    String scannerURI = response.getLocation();
+    assertNotNull(scannerURI);
+
+    // get a cell set
+    response = client.get(scannerURI, MIMETYPE_XML);
+    assertEquals(response.getCode(), 200);
+    CellSetModel cells = (CellSetModel)
+      unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+
+    int rows = cells.getRows().size();
+    assertTrue("Scanned too many rows! Only expected " + expectedRows + 
+        " total but scanned " + rows, expectedRows == rows);
+    for (RowModel row: cells.getRows()) {
+      int count = row.getCells().size();
+      assertEquals("Expected " + expectedKeys + " keys per row but " +
+        "returned " + count, expectedKeys, count);
+    }
+
+    // delete the scanner
+    response = client.delete(scannerURI);
+    assertEquals(response.getCode(), 200);
+  }
+
+  private void verifyScanFull(Scan s, KeyValue [] kvs) throws Exception {
+    ScannerModel model = ScannerModel.fromScan(s);
+    model.setBatch(Integer.MAX_VALUE); // fetch it all at once
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(model, writer);
+    LOG.debug(writer.toString());
+    byte[] body = Bytes.toBytes(writer.toString());
+    Response response = client.put("/" + getName() + "/scanner", MIMETYPE_XML,
+      body);
+    assertEquals(response.getCode(), 201);
+    String scannerURI = response.getLocation();
+    assertNotNull(scannerURI);
+
+    // get a cell set
+    response = client.get(scannerURI, MIMETYPE_XML);
+    assertEquals(response.getCode(), 200);
+    CellSetModel cellSet = (CellSetModel)
+      unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+
+    // delete the scanner
+    response = client.delete(scannerURI);
+    assertEquals(response.getCode(), 200);
+
+    int row = 0;
+    int idx = 0;
+    Iterator<RowModel> i = cellSet.getRows().iterator();
+    for (boolean done = true; done; row++) {
+      done = i.hasNext();
+      if (!done) break;
+      RowModel rowModel = i.next();
+      List<CellModel> cells = rowModel.getCells();
+      if (cells.isEmpty()) break;
+      assertTrue("Scanned too many keys! Only expected " + kvs.length + 
+        " total but already scanned " + (cells.size() + idx), 
+        kvs.length >= idx + cells.size());
+      for (CellModel cell: cells) {
+        assertTrue("Row mismatch", 
+            Bytes.equals(rowModel.getKey(), kvs[idx].getRow()));
+        byte[][] split = KeyValue.parseColumn(cell.getColumn());
+        assertTrue("Family mismatch", 
+            Bytes.equals(split[0], kvs[idx].getFamily()));
+        assertTrue("Qualifier mismatch", 
+            Bytes.equals(split[1], kvs[idx].getQualifier()));
+        assertTrue("Value mismatch", 
+            Bytes.equals(cell.getValue(), kvs[idx].getValue()));
+        idx++;
+      }
+    }
+    assertEquals("Expected " + kvs.length + " total keys but scanned " + idx,
+      kvs.length, idx);
+  }
+
+  private void verifyScanNoEarlyOut(Scan s, long expectedRows, long expectedKeys) 
+      throws Exception {
+    ScannerModel model = ScannerModel.fromScan(s);
+    model.setBatch(Integer.MAX_VALUE); // fetch it all at once
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(model, writer);
+    LOG.debug(writer.toString());
+    byte[] body = Bytes.toBytes(writer.toString());
+    Response response = client.put("/" + getName() + "/scanner", MIMETYPE_XML,
+      body);
+    assertEquals(response.getCode(), 201);
+    String scannerURI = response.getLocation();
+    assertNotNull(scannerURI);
+
+    // get a cell set
+    response = client.get(scannerURI, MIMETYPE_XML);
+    assertEquals(response.getCode(), 200);
+    CellSetModel cellSet = (CellSetModel)
+      unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+
+    // delete the scanner
+    response = client.delete(scannerURI);
+    assertEquals(response.getCode(), 200);
+
+    Iterator<RowModel> i = cellSet.getRows().iterator();
+    int j = 0;
+    for (boolean done = true; done; j++) {
+      done = i.hasNext();
+      if (!done) break;
+      RowModel rowModel = i.next();
+      List<CellModel> cells = rowModel.getCells();
+      if (cells.isEmpty()) break;
+      assertTrue("Scanned too many rows! Only expected " + expectedRows + 
+        " total but already scanned " + (j+1), expectedRows > j);
+      assertEquals("Expected " + expectedKeys + " keys per row but " +
+        "returned " + cells.size(), expectedKeys, cells.size());
+    }
+    assertEquals("Expected " + expectedRows + " rows but scanned " + j +
+      " rows", expectedRows, j);
+  }
+
+  public void testNoFilter() throws Exception {
+    // No filter
+    long expectedRows = this.numRows;
+    long expectedKeys = this.colsPerRow;
+    
+    // Both families
+    Scan s = new Scan();
+    verifyScan(s, expectedRows, expectedKeys);
+
+    // One family
+    s = new Scan();
+    s.addFamily(FAMILIES[0]);
+    verifyScan(s, expectedRows, expectedKeys/2);
+  }
+
+  public void testPrefixFilter() throws Exception {
+    // Grab rows from group one (half of total)
+    long expectedRows = this.numRows / 2;
+    long expectedKeys = this.colsPerRow;
+    Scan s = new Scan();
+    s.setFilter(new PrefixFilter(Bytes.toBytes("testRowOne")));
+    verifyScan(s, expectedRows, expectedKeys);
+  }
+
+  public void testPageFilter() throws Exception {
+    
+    // KVs in first 6 rows
+    KeyValue [] expectedKVs = {
+      // testRowOne-0
+      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+      new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+      new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+      // testRowOne-2
+      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+      new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+      new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+      // testRowOne-3
+      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+      new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+      new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+      // testRowTwo-0
+      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+      new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+      new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+      // testRowTwo-2
+      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+      new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+      new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+      // testRowTwo-3
+      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+      new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+      new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1])
+    };
+    
+    // Grab all 6 rows
+    long expectedRows = 6;
+    long expectedKeys = this.colsPerRow;
+    Scan s = new Scan();
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScan(s, expectedRows, expectedKeys);
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScanFull(s, expectedKVs);
+    
+    // Grab first 4 rows (6 cols per row)
+    expectedRows = 4;
+    expectedKeys = this.colsPerRow;
+    s = new Scan();
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScan(s, expectedRows, expectedKeys);
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScanFull(s, Arrays.copyOf(expectedKVs, 24));
+    
+    // Grab first 2 rows
+    expectedRows = 2;
+    expectedKeys = this.colsPerRow;
+    s = new Scan();
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScan(s, expectedRows, expectedKeys);
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScanFull(s, Arrays.copyOf(expectedKVs, 12));
+
+    // Grab first row
+    expectedRows = 1;
+    expectedKeys = this.colsPerRow;
+    s = new Scan();
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScan(s, expectedRows, expectedKeys);
+    s.setFilter(new PageFilter(expectedRows));
+    verifyScanFull(s, Arrays.copyOf(expectedKVs, 6));    
+  }
+
+  public void testInclusiveStopFilter() throws Exception {
+
+    // Grab rows from group one
+    
+    // If we just use start/stop row, we get total/2 - 1 rows
+    long expectedRows = (this.numRows / 2) - 1;
+    long expectedKeys = this.colsPerRow;
+    Scan s = new Scan(Bytes.toBytes("testRowOne-0"), 
+        Bytes.toBytes("testRowOne-3"));
+    verifyScan(s, expectedRows, expectedKeys);
+    
+    // Now use start row with inclusive stop filter
+    expectedRows = this.numRows / 2;
+    s = new Scan(Bytes.toBytes("testRowOne-0"));
+    s.setFilter(new InclusiveStopFilter(Bytes.toBytes("testRowOne-3")));
+    verifyScan(s, expectedRows, expectedKeys);
+
+    // Grab rows from group two
+    
+    // If we just use start/stop row, we get total/2 - 1 rows
+    expectedRows = (this.numRows / 2) - 1;
+    expectedKeys = this.colsPerRow;
+    s = new Scan(Bytes.toBytes("testRowTwo-0"), 
+        Bytes.toBytes("testRowTwo-3"));
+    verifyScan(s, expectedRows, expectedKeys);
+    
+    // Now use start row with inclusive stop filter
+    expectedRows = this.numRows / 2;
+    s = new Scan(Bytes.toBytes("testRowTwo-0"));
+    s.setFilter(new InclusiveStopFilter(Bytes.toBytes("testRowTwo-3")));
+    verifyScan(s, expectedRows, expectedKeys);
+
+  }
+  
+  public void testQualifierFilter() throws Exception {
+    
+    // Match two keys (one from each family) in half the rows
+    long expectedRows = this.numRows / 2;
+    long expectedKeys = 2;
+    Filter f = new QualifierFilter(CompareOp.EQUAL,
+        new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+    Scan s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys less than same qualifier
+    // Expect only two keys (one from each family) in half the rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = 2;
+    f = new QualifierFilter(CompareOp.LESS,
+        new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys less than or equal
+    // Expect four keys (two from each family) in half the rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = 4;
+    f = new QualifierFilter(CompareOp.LESS_OR_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys not equal
+    // Expect four keys (two from each family)
+    // Only look in first group of rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = 4;
+    f = new QualifierFilter(CompareOp.NOT_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+    s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys greater or equal
+    // Expect four keys (two from each family)
+    // Only look in first group of rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = 4;
+    f = new QualifierFilter(CompareOp.GREATER_OR_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+    s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys greater
+    // Expect two keys (one from each family)
+    // Only look in first group of rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = 2;
+    f = new QualifierFilter(CompareOp.GREATER,
+        new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+    s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys not equal to
+    // Look across rows and fully validate the keys and ordering
+    // Expect varied numbers of keys, 4 per row in group one, 6 per row in group two
+    f = new QualifierFilter(CompareOp.NOT_EQUAL,
+        new BinaryComparator(QUALIFIERS_ONE[2]));
+    s = new Scan();
+    s.setFilter(f);
+    
+    KeyValue [] kvs = {
+        // testRowOne-0
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowOne-2
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowOne-3
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowTwo-0
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-2
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-3
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+    };
+    verifyScanFull(s, kvs);
+     
+    
+    // Test across rows and groups with a regex
+    // Filter out "test*-2"
+    // Expect 4 keys per row across both groups
+    f = new QualifierFilter(CompareOp.NOT_EQUAL,
+        new RegexStringComparator("test.+-2"));
+    s = new Scan();
+    s.setFilter(f);
+    
+    kvs = new KeyValue [] {
+        // testRowOne-0
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowOne-2
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowOne-3
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowTwo-0
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-2
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-3
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+    };
+    verifyScanFull(s, kvs);
+     
+  }
+  
+  public void testRowFilter() throws Exception {
+
+    // Match a single row, all keys
+    long expectedRows = 1;
+    long expectedKeys = this.colsPerRow;
+    Filter f = new RowFilter(CompareOp.EQUAL,
+        new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+    Scan s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match a two rows, one from each group, using regex
+    expectedRows = 2;
+    expectedKeys = this.colsPerRow;
+    f = new RowFilter(CompareOp.EQUAL,
+        new RegexStringComparator("testRow.+-2"));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match rows less than
+    // Expect all keys in one row
+    expectedRows = 1;
+    expectedKeys = this.colsPerRow;
+    f = new RowFilter(CompareOp.LESS,
+        new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match rows less than or equal
+    // Expect all keys in two rows
+    expectedRows = 2;
+    expectedKeys = this.colsPerRow;
+    f = new RowFilter(CompareOp.LESS_OR_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match rows not equal
+    // Expect all keys in all but one row
+    expectedRows = this.numRows - 1;
+    expectedKeys = this.colsPerRow;
+    f = new RowFilter(CompareOp.NOT_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys greater or equal
+    // Expect all keys in all but one row
+    expectedRows = this.numRows - 1;
+    expectedKeys = this.colsPerRow;
+    f = new RowFilter(CompareOp.GREATER_OR_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match keys greater
+    // Expect all keys in all but two rows
+    expectedRows = this.numRows - 2;
+    expectedKeys = this.colsPerRow;
+    f = new RowFilter(CompareOp.GREATER,
+        new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match rows not equal to testRowTwo-2
+    // Look across rows and fully validate the keys and ordering
+    // Should see all keys in all rows but testRowTwo-2
+    f = new RowFilter(CompareOp.NOT_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+    s = new Scan();
+    s.setFilter(f);
+    
+    KeyValue [] kvs = {
+        // testRowOne-0
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+        new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowOne-3
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowTwo-0
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-2
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-3
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+    };
+    verifyScanFull(s, kvs);
+     
+    
+    // Test across rows and groups with a regex
+    // Filter out everything that doesn't match "*-2"
+    // Expect all keys in two rows
+    f = new RowFilter(CompareOp.EQUAL,
+        new RegexStringComparator(".+-2"));
+    s = new Scan();
+    s.setFilter(f);
+    
+    kvs = new KeyValue [] {
+        // testRowOne-2
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+        // testRowTwo-2
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1])
+    };
+    verifyScanFull(s, kvs);
+     
+  }
+  
+  public void testValueFilter() throws Exception {
+    
+    // Match group one rows
+    long expectedRows = this.numRows / 2;
+    long expectedKeys = this.colsPerRow;
+    Filter f = new ValueFilter(CompareOp.EQUAL,
+        new BinaryComparator(Bytes.toBytes("testValueOne")));
+    Scan s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+    // Match group two rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.EQUAL,
+        new BinaryComparator(Bytes.toBytes("testValueTwo")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match all values using regex
+    expectedRows = this.numRows;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.EQUAL,
+        new RegexStringComparator("testValue((One)|(Two))"));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match values less than
+    // Expect group one rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.LESS,
+        new BinaryComparator(Bytes.toBytes("testValueTwo")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match values less than or equal
+    // Expect all rows
+    expectedRows = this.numRows;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.LESS_OR_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testValueTwo")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+    // Match values less than or equal
+    // Expect group one rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.LESS_OR_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testValueOne")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match values not equal
+    // Expect half the rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.NOT_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testValueOne")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match values greater or equal
+    // Expect all rows
+    expectedRows = this.numRows;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.GREATER_OR_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testValueOne")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match values greater
+    // Expect half rows
+    expectedRows = this.numRows / 2;
+    expectedKeys = this.colsPerRow;
+    f = new ValueFilter(CompareOp.GREATER,
+        new BinaryComparator(Bytes.toBytes("testValueOne")));
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+    
+    // Match values not equal to testValueOne
+    // Look across rows and fully validate the keys and ordering
+    // Should see all keys in all group two rows
+    f = new ValueFilter(CompareOp.NOT_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testValueOne")));
+    s = new Scan();
+    s.setFilter(f);
+    
+    KeyValue [] kvs = {
+        // testRowTwo-0
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-2
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-3
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+    };
+    verifyScanFull(s, kvs);
+  }
+  
+  public void testSkipFilter() throws Exception {
+    
+    // Test for qualifier regex: "testQualifierOne-2"
+    // Should only get rows from second group, and all keys
+    Filter f = new SkipFilter(new QualifierFilter(CompareOp.NOT_EQUAL,
+        new BinaryComparator(Bytes.toBytes("testQualifierOne-2"))));
+    Scan s = new Scan();
+    s.setFilter(f);
+    
+    KeyValue [] kvs = {
+        // testRowTwo-0
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-2
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+        // testRowTwo-3
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+    };
+    verifyScanFull(s, kvs);
+  }
+    
+  public void testFilterList() throws Exception {
+    
+    // Test getting a single row, single key using Row, Qualifier, and Value 
+    // regular expression and substring filters
+    // Use must pass all
+    List<Filter> filters = new ArrayList<Filter>();
+    filters.add(new RowFilter(CompareOp.EQUAL, new RegexStringComparator(".+-2")));
+    filters.add(new QualifierFilter(CompareOp.EQUAL, new RegexStringComparator(".+-2")));
+    filters.add(new ValueFilter(CompareOp.EQUAL, new SubstringComparator("One")));
+    Filter f = new FilterList(Operator.MUST_PASS_ALL, filters);
+    Scan s = new Scan();
+    s.addFamily(FAMILIES[0]);
+    s.setFilter(f);
+    KeyValue [] kvs = {
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0])
+    };
+    verifyScanFull(s, kvs);
+
+    // Test getting everything with a MUST_PASS_ONE filter including row, qf, val
+    // regular expression and substring filters
+    filters.clear();
+    filters.add(new RowFilter(CompareOp.EQUAL, new RegexStringComparator(".+Two.+")));
+    filters.add(new QualifierFilter(CompareOp.EQUAL, new RegexStringComparator(".+-2")));
+    filters.add(new ValueFilter(CompareOp.EQUAL, new SubstringComparator("One")));
+    f = new FilterList(Operator.MUST_PASS_ONE, filters);
+    s = new Scan();
+    s.setFilter(f);
+    verifyScanNoEarlyOut(s, this.numRows, this.colsPerRow);    
+  }
+  
+  public void testFirstKeyOnlyFilter() throws Exception {
+    Scan s = new Scan();
+    s.setFilter(new FirstKeyOnlyFilter());
+    // Expected KVs, the first KV from each of the remaining 6 rows
+    KeyValue [] kvs = {
+        new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+        new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+        new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1])
+    };
+    verifyScanFull(s, kvs);
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestSchemaResource.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestSchemaResource.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestSchemaResource.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestSchemaResource.java Tue May 18 18:49:12 2010
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.rest.client.Cluster;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.apache.hadoop.hbase.rest.model.ColumnSchemaModel;
+import org.apache.hadoop.hbase.rest.model.TableSchemaModel;
+import org.apache.hadoop.hbase.rest.model.TestTableSchemaModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestSchemaResource extends HBaseRESTClusterTestBase {
+  private Client client;
+  private JAXBContext context;
+  private HBaseAdmin admin;
+
+  private static String TABLE1 = "TestSchemaResource1";
+  private static String TABLE2 = "TestSchemaResource2";
+
+  public TestSchemaResource() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(
+        ColumnSchemaModel.class,
+        TableSchemaModel.class);
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    admin = new HBaseAdmin(conf);
+    client = new Client(new Cluster().add("localhost", testServletPort));
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    client.shutdown();
+    super.tearDown();
+  }
+
+  private byte[] toXML(TableSchemaModel model) throws JAXBException {
+    StringWriter writer = new StringWriter();
+    context.createMarshaller().marshal(model, writer);
+    return Bytes.toBytes(writer.toString());
+  }
+
+  private TableSchemaModel fromXML(byte[] content) throws JAXBException {
+    return (TableSchemaModel) context.createUnmarshaller()
+      .unmarshal(new ByteArrayInputStream(content));
+  }
+
+  public void testTableCreateAndDeleteXML() 
+      throws IOException, JAXBException {
+    String schemaPath = "/" + TABLE1 + "/schema";
+    TableSchemaModel model;
+    Response response;
+
+    assertFalse(admin.tableExists(TABLE1));
+
+    // create the table
+    model = TestTableSchemaModel.buildTestModel(TABLE1);
+    TestTableSchemaModel.checkModel(model, TABLE1);
+    response = client.put(schemaPath, MIMETYPE_XML, toXML(model));
+    assertEquals(response.getCode(), 201);
+
+    // make sure HBase concurs, and wait for the table to come online
+    admin.enableTable(TABLE1);
+
+    // retrieve the schema and validate it
+    response = client.get(schemaPath, MIMETYPE_XML);
+    assertEquals(response.getCode(), 200);
+    model = fromXML(response.getBody());
+    TestTableSchemaModel.checkModel(model, TABLE1);
+
+    // delete the table
+    client.delete(schemaPath);
+
+    // make sure HBase concurs
+    assertFalse(admin.tableExists(TABLE1));
+  }
+
+  public void testTableCreateAndDeletePB() throws IOException, JAXBException {
+    String schemaPath = "/" + TABLE2 + "/schema";
+    TableSchemaModel model;
+    Response response;
+
+    assertFalse(admin.tableExists(TABLE2));
+
+    // create the table
+    model = TestTableSchemaModel.buildTestModel(TABLE2);
+    TestTableSchemaModel.checkModel(model, TABLE2);
+    response = client.put(schemaPath, Constants.MIMETYPE_PROTOBUF,
+      model.createProtobufOutput());
+    assertEquals(response.getCode(), 201);
+
+    // make sure HBase concurs, and wait for the table to come online
+    admin.enableTable(TABLE2);
+
+    // retrieve the schema and validate it
+    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
+    assertEquals(response.getCode(), 200);
+    model = new TableSchemaModel();
+    model.getObjectFromMessage(response.getBody());
+    TestTableSchemaModel.checkModel(model, TABLE2);
+
+    // delete the table
+    client.delete(schemaPath);
+
+    // make sure HBase concurs
+    assertFalse(admin.tableExists(TABLE2));
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java Tue May 18 18:49:12 2010
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.rest.client.Cluster;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.apache.hadoop.hbase.rest.model.StorageClusterStatusModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestStatusResource extends HBaseRESTClusterTestBase {
+  private static final byte[] ROOT_REGION_NAME = Bytes.toBytes("-ROOT-,,0");
+  private static final byte[] META_REGION_NAME = Bytes.toBytes(".META.,,1");
+
+  private Client client;
+  private JAXBContext context;
+  
+  public TestStatusResource() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(
+        StorageClusterStatusModel.class);
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    client = new Client(new Cluster().add("localhost", testServletPort));
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    client.shutdown();
+    super.tearDown();
+  }
+
+  private void validate(StorageClusterStatusModel model) {
+    assertNotNull(model);
+    assertTrue(model.getRegions() >= 2);
+    assertTrue(model.getRequests() >= 0);
+    // assumes minicluster with two regionservers
+    assertTrue(model.getAverageLoad() >= 1.0);
+    assertNotNull(model.getLiveNodes());
+    assertNotNull(model.getDeadNodes());
+    assertFalse(model.getLiveNodes().isEmpty());
+    boolean foundRoot = false, foundMeta = false;
+    for (StorageClusterStatusModel.Node node: model.getLiveNodes()) {
+      assertNotNull(node.getName());
+      assertTrue(node.getStartCode() > 0L);
+      assertTrue(node.getRequests() >= 0);
+      assertFalse(node.getRegions().isEmpty());
+      for (StorageClusterStatusModel.Node.Region region: node.getRegions()) {
+        if (Bytes.equals(region.getName(), ROOT_REGION_NAME)) {
+          foundRoot = true;
+        } else if (Bytes.equals(region.getName(), META_REGION_NAME)) {
+          foundMeta = true;
+        }
+      }
+    }
+    assertTrue(foundRoot);
+    assertTrue(foundMeta);
+  }
+
+  public void testGetClusterStatusXML() throws IOException, JAXBException {
+    Response response = client.get("/status/cluster", MIMETYPE_XML);
+    assertEquals(response.getCode(), 200);
+    StorageClusterStatusModel model = (StorageClusterStatusModel)
+      context.createUnmarshaller().unmarshal(
+        new ByteArrayInputStream(response.getBody()));
+    validate(model);
+  }
+  
+  public void testGetClusterStatusPB() throws IOException {
+    Response response = client.get("/status/cluster", MIMETYPE_PROTOBUF);
+    assertEquals(response.getCode(), 200);
+    StorageClusterStatusModel model = new StorageClusterStatusModel();
+    model.getObjectFromMessage(response.getBody());
+    validate(model);
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestTableResource.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestTableResource.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestTableResource.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestTableResource.java Tue May 18 18:49:12 2010
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.rest.client.Cluster;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.apache.hadoop.hbase.rest.model.TableModel;
+import org.apache.hadoop.hbase.rest.model.TableInfoModel;
+import org.apache.hadoop.hbase.rest.model.TableListModel;
+import org.apache.hadoop.hbase.rest.model.TableRegionModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestTableResource extends HBaseRESTClusterTestBase {
+  private static String TABLE = "TestTableResource";
+  private static String COLUMN = "test:";
+
+  private Client client;
+  private JAXBContext context;
+  private HBaseAdmin admin;
+
+  public TestTableResource() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(
+        TableModel.class,
+        TableInfoModel.class,
+        TableListModel.class,
+        TableRegionModel.class);
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    client = new Client(new Cluster().add("localhost", testServletPort));
+    admin = new HBaseAdmin(conf);
+    if (admin.tableExists(TABLE)) {
+      return;
+    }
+    HTableDescriptor htd = new HTableDescriptor(TABLE);
+    htd.addFamily(new HColumnDescriptor(KeyValue.parseColumn(
+        Bytes.toBytes(COLUMN))[0]));
+    admin.createTable(htd);
+    new HTable(conf, TABLE);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    client.shutdown();
+    super.tearDown();
+  }
+
+  private void checkTableList(TableListModel model) {
+    boolean found = false;
+    Iterator<TableModel> tables = model.getTables().iterator();
+    assertTrue(tables.hasNext());
+    while (tables.hasNext()) {
+      TableModel table = tables.next();
+      if (table.getName().equals(TABLE)) {
+        found = true;
+        break;
+      }
+    }
+    assertTrue(found);
+  }
+
+  public void testTableListText() throws IOException {
+    Response response = client.get("/", MIMETYPE_TEXT);
+    assertEquals(response.getCode(), 200);
+  }
+
+  public void testTableListXML() throws IOException, JAXBException {
+    Response response = client.get("/", MIMETYPE_XML);
+    assertEquals(response.getCode(), 200);
+    TableListModel model = (TableListModel)
+      context.createUnmarshaller()
+        .unmarshal(new ByteArrayInputStream(response.getBody()));
+    checkTableList(model);
+  }
+
+  public void testTableListJSON() throws IOException {
+    Response response = client.get("/", MIMETYPE_JSON);
+    assertEquals(response.getCode(), 200);
+  }
+
+  public void testTableListPB() throws IOException, JAXBException {
+    Response response = client.get("/", MIMETYPE_PROTOBUF);
+    assertEquals(response.getCode(), 200);
+    TableListModel model = new TableListModel();
+    model.getObjectFromMessage(response.getBody());
+    checkTableList(model);
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestVersionResource.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestVersionResource.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestVersionResource.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/TestVersionResource.java Tue May 18 18:49:12 2010
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.rest.client.Cluster;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.apache.hadoop.hbase.rest.model.StorageClusterVersionModel;
+import org.apache.hadoop.hbase.rest.model.VersionModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+public class TestVersionResource extends HBaseRESTClusterTestBase {
+  private static final Log LOG =
+    LogFactory.getLog(TestVersionResource.class);
+
+  private Client client;
+  private JAXBContext context;
+
+  public TestVersionResource() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(
+        VersionModel.class,
+        StorageClusterVersionModel.class);
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    client = new Client(new Cluster().add("localhost", testServletPort));
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    client.shutdown();
+    super.tearDown();
+  }
+
+  private static void validate(VersionModel model) {
+    assertNotNull(model);
+    assertNotNull(model.getRESTVersion());
+    assertEquals(model.getRESTVersion(), RESTServlet.VERSION_STRING);
+    String osVersion = model.getOSVersion(); 
+    assertNotNull(osVersion);
+    assertTrue(osVersion.contains(System.getProperty("os.name")));
+    assertTrue(osVersion.contains(System.getProperty("os.version")));
+    assertTrue(osVersion.contains(System.getProperty("os.arch")));
+    String jvmVersion = model.getJVMVersion();
+    assertNotNull(jvmVersion);
+    assertTrue(jvmVersion.contains(System.getProperty("java.vm.vendor")));
+    assertTrue(jvmVersion.contains(System.getProperty("java.version")));
+    assertTrue(jvmVersion.contains(System.getProperty("java.vm.version")));
+    assertNotNull(model.getServerVersion());
+    String jerseyVersion = model.getJerseyVersion();
+    assertNotNull(jerseyVersion);
+    assertEquals(jerseyVersion, ServletContainer.class.getPackage()
+      .getImplementationVersion());
+  }
+
+  public void testGetStargateVersionText() throws IOException {
+    Response response = client.get("/version", MIMETYPE_TEXT);
+    assertTrue(response.getCode() == 200);
+    String body = Bytes.toString(response.getBody());
+    assertTrue(body.length() > 0);
+    assertTrue(body.contains(RESTServlet.VERSION_STRING));
+    assertTrue(body.contains(System.getProperty("java.vm.vendor")));
+    assertTrue(body.contains(System.getProperty("java.version")));
+    assertTrue(body.contains(System.getProperty("java.vm.version")));
+    assertTrue(body.contains(System.getProperty("os.name")));
+    assertTrue(body.contains(System.getProperty("os.version")));
+    assertTrue(body.contains(System.getProperty("os.arch")));
+    assertTrue(body.contains(ServletContainer.class.getPackage()
+      .getImplementationVersion()));
+  }
+
+  public void testGetStargateVersionXML() throws IOException, JAXBException {
+    Response response = client.get("/version", MIMETYPE_XML);
+    assertTrue(response.getCode() == 200);
+    VersionModel model = (VersionModel)
+      context.createUnmarshaller().unmarshal(
+        new ByteArrayInputStream(response.getBody()));
+    validate(model);
+    LOG.info("success retrieving Stargate version as XML");
+  }
+
+  public void testGetStargateVersionJSON() throws IOException {
+    Response response = client.get("/version", MIMETYPE_JSON);
+    assertTrue(response.getCode() == 200);
+  }
+
+  public void testGetStargateVersionPB() throws IOException {
+    Response response = client.get("/version", MIMETYPE_PROTOBUF);
+    assertTrue(response.getCode() == 200);
+    VersionModel model = new VersionModel();
+    model.getObjectFromMessage(response.getBody());
+    validate(model);
+    LOG.info("success retrieving Stargate version as protobuf");
+  }
+
+  public void testGetStorageClusterVersionText() throws IOException {
+    Response response = client.get("/version/cluster", MIMETYPE_TEXT);
+    assertTrue(response.getCode() == 200);
+  }
+
+  public void testGetStorageClusterVersionXML() throws IOException,
+      JAXBException {
+    Response response = client.get("/version/cluster", MIMETYPE_XML);
+    assertTrue(response.getCode() == 200);
+    StorageClusterVersionModel clusterVersionModel = 
+      (StorageClusterVersionModel)
+        context.createUnmarshaller().unmarshal(
+          new ByteArrayInputStream(response.getBody()));
+    assertNotNull(clusterVersionModel);
+    assertNotNull(clusterVersionModel.getVersion());
+    LOG.info("success retrieving storage cluster version as XML");
+  }
+
+  public void testGetStorageClusterVersionJSON() throws IOException {
+    Response response = client.get("/version/cluster", MIMETYPE_JSON);
+    assertTrue(response.getCode() == 200);
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteAdmin.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteAdmin.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteAdmin.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteAdmin.java Tue May 18 18:49:12 2010
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest.client;
+
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.rest.HBaseRESTClusterTestBase;
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestRemoteAdmin extends HBaseRESTClusterTestBase {
+
+  static final String TABLE_1 = "TestRemoteAdmin_Table_1";
+  static final String TABLE_2 = "TestRemoteAdmin_Table_2";
+  static final byte[] COLUMN_1 = Bytes.toBytes("a");
+
+  static final HTableDescriptor DESC_1;
+  static {
+    DESC_1 = new HTableDescriptor(TABLE_1);
+    DESC_1.addFamily(new HColumnDescriptor(COLUMN_1));
+  }
+  static final HTableDescriptor DESC_2;
+  static {
+    DESC_2 = new HTableDescriptor(TABLE_2);
+    DESC_2.addFamily(new HColumnDescriptor(COLUMN_1));
+  }
+
+  Client client;
+  HBaseAdmin localAdmin;
+  RemoteAdmin remoteAdmin;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    localAdmin = new HBaseAdmin(conf);
+    remoteAdmin = new RemoteAdmin(new Client(
+        new Cluster().add("localhost", testServletPort)),
+      conf);
+    if (localAdmin.tableExists(TABLE_1)) {
+      localAdmin.disableTable(TABLE_1);
+      localAdmin.deleteTable(TABLE_1);
+    }
+    if (!localAdmin.tableExists(TABLE_2)) {
+      localAdmin.createTable(DESC_2);
+    }
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    super.tearDown();
+  }
+
+  public void testCreateTable() throws Exception {
+    assertFalse(remoteAdmin.isTableAvailable(TABLE_1));
+    remoteAdmin.createTable(DESC_1);
+    assertTrue(remoteAdmin.isTableAvailable(TABLE_1));
+  }
+
+  public void testDeleteTable() throws Exception {
+    assertTrue(remoteAdmin.isTableAvailable(TABLE_2));
+    remoteAdmin.deleteTable(TABLE_2);
+    assertFalse(remoteAdmin.isTableAvailable(TABLE_2));
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java Tue May 18 18:49:12 2010
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest.client;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Get;
+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.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.rest.HBaseRESTClusterTestBase;
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.rest.client.Cluster;
+import org.apache.hadoop.hbase.rest.client.RemoteHTable;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestRemoteTable extends HBaseRESTClusterTestBase {
+
+  static final String TABLE = "TestRemoteTable";
+  static final byte[] ROW_1 = Bytes.toBytes("testrow1");
+  static final byte[] ROW_2 = Bytes.toBytes("testrow2");
+  static final byte[] ROW_3 = Bytes.toBytes("testrow3");
+  static final byte[] ROW_4 = Bytes.toBytes("testrow4");
+  static final byte[] COLUMN_1 = Bytes.toBytes("a");
+  static final byte[] COLUMN_2 = Bytes.toBytes("b");
+  static final byte[] COLUMN_3 = Bytes.toBytes("c");
+  static final byte[] QUALIFIER_1 = Bytes.toBytes("1");
+  static final byte[] QUALIFIER_2 = Bytes.toBytes("2");
+  static final byte[] QUALIFIER_3 = Bytes.toBytes("3");
+  static final byte[] VALUE_1 = Bytes.toBytes("testvalue1");
+  static final byte[] VALUE_2 = Bytes.toBytes("testvalue2");
+  static final byte[] VALUE_3 = Bytes.toBytes("testvalue3");
+
+  static final long ONE_HOUR = 60 * 60 * 1000;
+  static final long TS_2 = System.currentTimeMillis();
+  static final long TS_1 = TS_2 - ONE_HOUR;
+
+  Client client;
+  HBaseAdmin admin;
+  RemoteHTable remoteTable;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    
+    admin = new HBaseAdmin(conf);
+    if (!admin.tableExists(TABLE)) {
+      HTableDescriptor htd = new HTableDescriptor(TABLE);
+      htd.addFamily(new HColumnDescriptor(COLUMN_1));
+      htd.addFamily(new HColumnDescriptor(COLUMN_2));
+      htd.addFamily(new HColumnDescriptor(COLUMN_3));
+      admin.createTable(htd);
+      HTable table = new HTable(TABLE);
+      Put put = new Put(ROW_1);
+      put.add(COLUMN_1, QUALIFIER_1, TS_2, VALUE_1);
+      table.put(put);
+      put = new Put(ROW_2);
+      put.add(COLUMN_1, QUALIFIER_1, TS_1, VALUE_1);
+      put.add(COLUMN_1, QUALIFIER_1, TS_2, VALUE_2);
+      put.add(COLUMN_2, QUALIFIER_2, TS_2, VALUE_2);
+      table.put(put);
+      table.flushCommits();
+    }
+    remoteTable = new RemoteHTable(
+      new Client(new Cluster().add("localhost", testServletPort)),
+        conf, TABLE, null);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    remoteTable.close();
+    super.tearDown();
+  }
+
+  public void testGetTableDescriptor() throws IOException {
+    HTableDescriptor local = new HTable(conf, TABLE).getTableDescriptor();
+    assertEquals(remoteTable.getTableDescriptor(), local);
+  }
+
+  public void testGet() throws IOException {
+    Get get = new Get(ROW_1);
+    Result result = remoteTable.get(get);
+    byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_1, value1));
+    assertNull(value2);
+
+    get = new Get(ROW_1);
+    get.addFamily(COLUMN_3);
+    result = remoteTable.get(get);
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNull(value1);
+    assertNull(value2);
+
+    get = new Get(ROW_1);
+    get.addColumn(COLUMN_1, QUALIFIER_1);
+    get.addColumn(COLUMN_2, QUALIFIER_2);
+    result = remoteTable.get(get);
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_1, value1));
+    assertNull(value2);
+
+    get = new Get(ROW_2);
+    result = remoteTable.get(get);    
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
+    assertNotNull(value2);
+    assertTrue(Bytes.equals(VALUE_2, value2));
+
+    get = new Get(ROW_2);
+    get.addFamily(COLUMN_1);
+    result = remoteTable.get(get);    
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
+    assertNull(value2);
+
+    get = new Get(ROW_2);
+    get.addColumn(COLUMN_1, QUALIFIER_1);
+    get.addColumn(COLUMN_2, QUALIFIER_2);
+    result = remoteTable.get(get);    
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
+    assertNotNull(value2);
+    assertTrue(Bytes.equals(VALUE_2, value2));
+
+    // test timestamp
+
+    get = new Get(ROW_2);
+    get.addFamily(COLUMN_1);
+    get.addFamily(COLUMN_2);
+    get.setTimeStamp(TS_1);
+    result = remoteTable.get(get);    
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
+    assertNull(value2);
+
+    // test timerange
+
+    get = new Get(ROW_2);
+    get.addFamily(COLUMN_1);
+    get.addFamily(COLUMN_2);
+    get.setTimeRange(0, TS_1 + 1);
+    result = remoteTable.get(get);    
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
+    assertNull(value2);
+
+    // test maxVersions
+
+    get = new Get(ROW_2);
+    get.addFamily(COLUMN_1);
+    get.setMaxVersions(2);
+    result = remoteTable.get(get);
+    int count = 0;
+    for (KeyValue kv: result.list()) {
+      if (Bytes.equals(COLUMN_1, kv.getFamily()) && TS_1 == kv.getTimestamp()) {
+        assertTrue(Bytes.equals(VALUE_1, kv.getValue())); // @TS_1
+        count++;
+      }
+      if (Bytes.equals(COLUMN_1, kv.getFamily()) && TS_2 == kv.getTimestamp()) {
+        assertTrue(Bytes.equals(VALUE_2, kv.getValue())); // @TS_2
+        count++;
+      }
+    }
+    assertEquals(2, count);
+  }
+
+  public void testPut() throws IOException {
+    Put put = new Put(ROW_3);
+    put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
+    remoteTable.put(put);
+
+    Get get = new Get(ROW_3);
+    get.addFamily(COLUMN_1);
+    Result result = remoteTable.get(get);
+    byte[] value = result.getValue(COLUMN_1, QUALIFIER_1);
+    assertNotNull(value);
+    assertTrue(Bytes.equals(VALUE_1, value));
+
+    // multiput
+
+    List<Put> puts = new ArrayList<Put>();
+    put = new Put(ROW_3);
+    put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
+    puts.add(put);
+    put = new Put(ROW_4);
+    put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
+    puts.add(put);
+    put = new Put(ROW_4);
+    put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
+    puts.add(put);
+    remoteTable.put(puts);
+
+    get = new Get(ROW_3);
+    get.addFamily(COLUMN_2);
+    result = remoteTable.get(get);
+    value = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value);
+    assertTrue(Bytes.equals(VALUE_2, value));
+    get = new Get(ROW_4);
+    result = remoteTable.get(get);
+    value = result.getValue(COLUMN_1, QUALIFIER_1);
+    assertNotNull(value);
+    assertTrue(Bytes.equals(VALUE_1, value));
+    value = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value);
+    assertTrue(Bytes.equals(VALUE_2, value));
+  }
+
+  public void testDelete() throws IOException {
+    Put put = new Put(ROW_3);
+    put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
+    put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
+    remoteTable.put(put);
+
+    Get get = new Get(ROW_3);
+    get.addFamily(COLUMN_1);
+    get.addFamily(COLUMN_2);
+    Result result = remoteTable.get(get);
+    byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_1, value1));
+    assertNotNull(value2);
+    assertTrue(Bytes.equals(VALUE_2, value2));
+
+    Delete delete = new Delete(ROW_3);
+    delete.deleteColumn(COLUMN_2, QUALIFIER_2);
+    remoteTable.delete(delete);
+    
+    get = new Get(ROW_3);
+    get.addFamily(COLUMN_1);
+    get.addFamily(COLUMN_2);
+    result = remoteTable.get(get);
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNotNull(value1);
+    assertTrue(Bytes.equals(VALUE_1, value1));
+    assertNull(value2);
+
+    delete = new Delete(ROW_3);
+    remoteTable.delete(delete);
+
+    get = new Get(ROW_3);
+    get.addFamily(COLUMN_1);
+    get.addFamily(COLUMN_2);
+    result = remoteTable.get(get);
+    value1 = result.getValue(COLUMN_1, QUALIFIER_1);
+    value2 = result.getValue(COLUMN_2, QUALIFIER_2);
+    assertNull(value1);
+    assertNull(value2);
+  }
+
+  public void testScanner() throws IOException {
+    List<Put> puts = new ArrayList<Put>();
+    Put put = new Put(ROW_1);
+    put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
+    puts.add(put);
+    put = new Put(ROW_2);
+    put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
+    puts.add(put);
+    put = new Put(ROW_3);
+    put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
+    puts.add(put);
+    put = new Put(ROW_4);
+    put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
+    puts.add(put);
+    remoteTable.put(puts);
+
+    ResultScanner scanner = remoteTable.getScanner(new Scan());
+
+    Result[] results = scanner.next(1);
+    assertNotNull(results);
+    assertEquals(1, results.length);
+    assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
+
+    results = scanner.next(3);
+    assertNotNull(results);
+    assertEquals(3, results.length);
+    assertTrue(Bytes.equals(ROW_2, results[0].getRow()));
+    assertTrue(Bytes.equals(ROW_3, results[1].getRow()));
+    assertTrue(Bytes.equals(ROW_4, results[2].getRow()));
+
+    results = scanner.next(1);
+    assertNull(results);
+
+    scanner.close();
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellModel.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellModel.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellModel.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellModel.java Tue May 18 18:49:12 2010
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest.model;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.hadoop.hbase.util.Base64;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import junit.framework.TestCase;
+
+public class TestCellModel extends TestCase {
+
+  private static final long TIMESTAMP = 1245219839331L;
+  private static final byte[] COLUMN = Bytes.toBytes("testcolumn");
+  private static final byte[] VALUE = Bytes.toBytes("testvalue");
+
+  private static final String AS_XML =
+    "<Cell timestamp=\"1245219839331\"" +
+      " column=\"dGVzdGNvbHVtbg==\">" +
+      "dGVzdHZhbHVl</Cell>";
+
+  private static final String AS_PB = 
+    "Egp0ZXN0Y29sdW1uGOO6i+eeJCIJdGVzdHZhbHVl";
+
+  private JAXBContext context;
+
+  public TestCellModel() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(CellModel.class);
+  }
+
+  private CellModel buildTestModel() {
+    CellModel model = new CellModel();
+    model.setColumn(COLUMN);
+    model.setTimestamp(TIMESTAMP);
+    model.setValue(VALUE);
+    return model;
+  }
+
+  @SuppressWarnings("unused")
+  private String toXML(CellModel model) throws JAXBException {
+    StringWriter writer = new StringWriter();
+    context.createMarshaller().marshal(model, writer);
+    return writer.toString();
+  }
+
+  private CellModel fromXML(String xml) throws JAXBException {
+    return (CellModel)
+      context.createUnmarshaller().unmarshal(new StringReader(xml));
+  }
+
+  @SuppressWarnings("unused")
+  private byte[] toPB(CellModel model) {
+    return model.createProtobufOutput();
+  }
+
+  private CellModel fromPB(String pb) throws IOException {
+    return (CellModel) 
+      new CellModel().getObjectFromMessage(Base64.decode(AS_PB));
+  }
+
+  private void checkModel(CellModel model) {
+    assertTrue(Bytes.equals(model.getColumn(), COLUMN));
+    assertTrue(Bytes.equals(model.getValue(), VALUE));
+    assertTrue(model.hasUserTimestamp());
+    assertEquals(model.getTimestamp(), TIMESTAMP);
+  }
+
+  public void testBuildModel() throws Exception {
+    checkModel(buildTestModel());
+  }
+
+  public void testFromXML() throws Exception {
+    checkModel(fromXML(AS_XML));
+  }
+
+  public void testFromPB() throws Exception {
+    checkModel(fromPB(AS_PB));
+  }
+}

Added: hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellSetModel.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellSetModel.java?rev=945816&view=auto
==============================================================================
--- hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellSetModel.java (added)
+++ hadoop/hbase/trunk/core/src/test/java/org/apache/hadoop/hbase/rest/model/TestCellSetModel.java Tue May 18 18:49:12 2010
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.hadoop.hbase.rest.model;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Iterator;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.hadoop.hbase.util.Base64;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import junit.framework.TestCase;
+
+public class TestCellSetModel extends TestCase {
+
+  private static final byte[] ROW1 = Bytes.toBytes("testrow1");
+  private static final byte[] COLUMN1 = Bytes.toBytes("testcolumn1");
+  private static final byte[] VALUE1 = Bytes.toBytes("testvalue1");
+  private static final long TIMESTAMP1 = 1245219839331L;
+  private static final byte[] ROW2 = Bytes.toBytes("testrow1");
+  private static final byte[] COLUMN2 = Bytes.toBytes("testcolumn2");
+  private static final byte[] VALUE2 = Bytes.toBytes("testvalue2");
+  private static final long TIMESTAMP2 = 1245239813319L;
+  private static final byte[] COLUMN3 = Bytes.toBytes("testcolumn3");
+  private static final byte[] VALUE3 = Bytes.toBytes("testvalue3");
+  private static final long TIMESTAMP3 = 1245393318192L;
+
+  private static final String AS_XML =
+    "<CellSet>" + 
+      "<Row key=\"dGVzdHJvdzE=\">" + 
+        "<Cell timestamp=\"1245219839331\" column=\"dGVzdGNvbHVtbjE=\">" + 
+          "dGVzdHZhbHVlMQ==</Cell>" + 
+        "</Row>" + 
+      "<Row key=\"dGVzdHJvdzE=\">" + 
+        "<Cell timestamp=\"1245239813319\" column=\"dGVzdGNvbHVtbjI=\">" +
+          "dGVzdHZhbHVlMg==</Cell>" + 
+        "<Cell timestamp=\"1245393318192\" column=\"dGVzdGNvbHVtbjM=\">" + 
+          "dGVzdHZhbHVlMw==</Cell>" + 
+        "</Row>" +
+      "</CellSet>";
+
+  private static final String AS_PB = 
+    "CiwKCHRlc3Ryb3cxEiASC3Rlc3Rjb2x1bW4xGOO6i+eeJCIKdGVzdHZhbHVlMQpOCgh0ZXN0cm93" +
+    "MRIgEgt0ZXN0Y29sdW1uMhjHyc7wniQiCnRlc3R2YWx1ZTISIBILdGVzdGNvbHVtbjMYsOLnuZ8k" +
+    "Igp0ZXN0dmFsdWUz";
+
+  private JAXBContext context;
+
+  public TestCellSetModel() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(
+        CellModel.class,
+        CellSetModel.class,
+        RowModel.class);
+  }
+
+  private CellSetModel buildTestModel() {
+    CellSetModel model = new CellSetModel();
+    RowModel row;
+    row = new RowModel();
+    row.setKey(ROW1);
+    row.addCell(new CellModel(COLUMN1, TIMESTAMP1, VALUE1));
+    model.addRow(row);
+    row = new RowModel();
+    row.setKey(ROW2);
+    row.addCell(new CellModel(COLUMN2, TIMESTAMP2, VALUE2));
+    row.addCell(new CellModel(COLUMN3, TIMESTAMP3, VALUE3));
+    model.addRow(row);
+    return model;
+  }
+
+  @SuppressWarnings("unused")
+  private String toXML(CellSetModel model) throws JAXBException {
+    StringWriter writer = new StringWriter();
+    context.createMarshaller().marshal(model, writer);
+    return writer.toString();
+  }
+
+  private CellSetModel fromXML(String xml) throws JAXBException {
+    return (CellSetModel)
+      context.createUnmarshaller().unmarshal(new StringReader(xml));
+  }
+
+  @SuppressWarnings("unused")
+  private byte[] toPB(CellSetModel model) {
+    return model.createProtobufOutput();
+  }
+
+  private CellSetModel fromPB(String pb) throws IOException {
+    return (CellSetModel) 
+      new CellSetModel().getObjectFromMessage(Base64.decode(AS_PB));
+  }
+
+  private void checkModel(CellSetModel model) {
+    Iterator<RowModel> rows = model.getRows().iterator();
+    RowModel row = rows.next();
+    assertTrue(Bytes.equals(ROW1, row.getKey()));
+    Iterator<CellModel> cells = row.getCells().iterator();
+    CellModel cell = cells.next();
+    assertTrue(Bytes.equals(COLUMN1, cell.getColumn()));
+    assertTrue(Bytes.equals(VALUE1, cell.getValue()));
+    assertTrue(cell.hasUserTimestamp());
+    assertEquals(cell.getTimestamp(), TIMESTAMP1);
+    assertFalse(cells.hasNext());
+    row = rows.next();
+    assertTrue(Bytes.equals(ROW2, row.getKey()));
+    cells = row.getCells().iterator();
+    cell = cells.next();
+    assertTrue(Bytes.equals(COLUMN2, cell.getColumn()));
+    assertTrue(Bytes.equals(VALUE2, cell.getValue()));
+    assertTrue(cell.hasUserTimestamp());
+    assertEquals(cell.getTimestamp(), TIMESTAMP2);
+    cell = cells.next();
+    assertTrue(Bytes.equals(COLUMN3, cell.getColumn()));
+    assertTrue(Bytes.equals(VALUE3, cell.getValue()));
+    assertTrue(cell.hasUserTimestamp());
+    assertEquals(cell.getTimestamp(), TIMESTAMP3);
+    assertFalse(cells.hasNext());
+  }
+
+  public void testBuildModel() throws Exception {
+    checkModel(buildTestModel());
+  }
+
+  public void testFromXML() throws Exception {
+    checkModel(fromXML(AS_XML));
+  }
+
+  public void testFromPB() throws Exception {
+    checkModel(fromPB(AS_PB));
+  }
+}



Mime
View raw message