hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From apurt...@apache.org
Subject svn commit: r928876 [11/13] - in /hadoop/hbase/trunk: ./ contrib/stargate/ contrib/stargate/conf/ contrib/stargate/core/ contrib/stargate/core/src/ contrib/stargate/core/src/main/ contrib/stargate/core/src/main/java/ contrib/stargate/core/src/main/java...
Date Mon, 29 Mar 2010 19:15:20 GMT
Added: hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/MiniClusterTestBase.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/MiniClusterTestBase.java?rev=928876&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/MiniClusterTestBase.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/MiniClusterTestBase.java Mon Mar 29 19:15:15 2010
@@ -0,0 +1,237 @@
+/*
+ * 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.stargate;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.MiniHBaseCluster;
+import org.apache.hadoop.hbase.MiniZooKeeperCluster;
+import org.apache.hadoop.hbase.client.HConnectionManager;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.util.FSUtils;
+import org.apache.hadoop.hdfs.MiniDFSCluster;
+import org.apache.hadoop.util.StringUtils;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+import junit.framework.TestCase;
+
+public class MiniClusterTestBase extends TestCase {
+  protected static final Log LOG =
+    LogFactory.getLog(MiniClusterTestBase.class);
+
+  public static final String MIMETYPE_BINARY = "application/octet-stream";
+  public static final String MIMETYPE_JSON = "application/json";
+  public static final String MIMETYPE_PLAIN = "text/plain";
+  public static final String MIMETYPE_PROTOBUF = "application/x-protobuf";
+  public static final String MIMETYPE_XML = "text/xml";
+
+  // use a nonstandard port
+  public static final int DEFAULT_TEST_PORT = 38080;
+
+  protected static Configuration conf = HBaseConfiguration.create();
+  protected static MiniZooKeeperCluster zooKeeperCluster;
+  protected static MiniHBaseCluster hbaseCluster;
+  protected static MiniDFSCluster dfsCluster;
+  protected static File testDir;
+  protected static int testServletPort;
+  protected static Server server;
+
+  public static boolean isMiniClusterRunning() {
+    return server != null;
+  }
+
+  private static void startDFS() throws Exception {
+    if (dfsCluster != null) {
+      LOG.error("MiniDFSCluster already running");
+      return;
+    }
+    // This spews a bunch of warnings about missing scheme. TODO: fix.
+    dfsCluster = new MiniDFSCluster(0, conf, 2, true, true, true,
+      null, null, null, null);
+    // mangle the conf so that the fs parameter points to the minidfs we
+    // just started up
+    FileSystem filesystem = dfsCluster.getFileSystem();
+    conf.set("fs.defaultFS", filesystem.getUri().toString());
+    Path parentdir = filesystem.getHomeDirectory();
+    conf.set(HConstants.HBASE_DIR, parentdir.toString());
+    filesystem.mkdirs(parentdir);
+    FSUtils.setVersion(filesystem, parentdir);
+  }
+
+  private static void stopDFS() {
+    if (dfsCluster != null) try {
+      FileSystem fs = dfsCluster.getFileSystem();
+      if (fs != null) {
+        LOG.info("Shutting down FileSystem");
+        fs.close();
+      }
+      FileSystem.closeAll();
+      dfsCluster = null;
+    } catch (Exception e) {
+      LOG.warn(StringUtils.stringifyException(e));
+    }
+  }
+
+  private static void startZooKeeper() throws Exception {
+    if (zooKeeperCluster != null) {
+      LOG.error("ZooKeeper already running");
+      return;
+    }
+    zooKeeperCluster = new MiniZooKeeperCluster();
+    zooKeeperCluster.startup(testDir);
+    LOG.info("started " + zooKeeperCluster.getClass().getName());
+  }
+
+  private static void stopZooKeeper() {
+    if (zooKeeperCluster != null) try {
+      zooKeeperCluster.shutdown();
+      zooKeeperCluster = null;
+    } catch (Exception e) {
+      LOG.warn(StringUtils.stringifyException(e));
+    }
+  }
+  
+  private static void startHBase() throws Exception {
+    if (hbaseCluster != null) {
+      LOG.error("MiniHBaseCluster already running");
+      return;
+    }
+    hbaseCluster = new MiniHBaseCluster(conf, 1);
+    // opening the META table ensures that cluster is running
+    new HTable(conf, HConstants.META_TABLE_NAME);
+    LOG.info("started MiniHBaseCluster");
+  }
+  
+  private static void stopHBase() {
+    if (hbaseCluster != null) try {
+      HConnectionManager.deleteConnectionInfo(conf, true);
+      hbaseCluster.shutdown();
+      hbaseCluster = null;
+    } catch (Exception e) {
+      LOG.warn(StringUtils.stringifyException(e));
+    }
+  }
+
+  private static void startServletContainer() throws Exception {
+    if (server != null) {
+      LOG.error("ServletContainer already running");
+      return;
+    }
+
+    // set up the Jersey servlet container for Jetty
+    ServletHolder sh = new ServletHolder(ServletContainer.class);
+    sh.setInitParameter(
+      "com.sun.jersey.config.property.resourceConfigClass",
+      ResourceConfig.class.getCanonicalName());
+    sh.setInitParameter("com.sun.jersey.config.property.packages",
+      "jetty");
+
+    LOG.info("configured " + ServletContainer.class.getName());
+    
+    // set up Jetty and run the embedded server
+    testServletPort = conf.getInt("test.stargate.port", DEFAULT_TEST_PORT);
+    server = new Server(testServletPort);
+    server.setSendServerVersion(false);
+    server.setSendDateHeader(false);
+      // set up context
+    Context context = new Context(server, "/", Context.SESSIONS);
+    context.addServlet(sh, "/*");
+      // start the server
+    server.start();
+
+    LOG.info("started " + server.getClass().getName() + " on port " + 
+      testServletPort);
+  }
+
+  private static void stopServletContainer() {
+    if (server != null) try {
+      server.stop();
+      server = null;
+    } catch (Exception e) {
+      LOG.warn(StringUtils.stringifyException(e));
+    }
+  }
+
+  public static void startMiniCluster() throws Exception {
+    try {
+      startDFS();
+      startZooKeeper();
+      startHBase();
+      startServletContainer();
+    } catch (Exception e) {
+      stopServletContainer();
+      stopHBase();
+      stopZooKeeper();
+      stopDFS();
+      throw e;
+    }
+  }
+
+  public static void stopMiniCluster() {
+    stopServletContainer();
+    stopHBase();
+    stopZooKeeper();
+    stopDFS();
+  }
+
+  static class MiniClusterShutdownThread extends Thread {
+    public void run() {
+      stopMiniCluster();
+      Path path = new Path(
+        conf.get("test.build.data",
+          System.getProperty("test.build.data", "build/test/data")));
+      try {
+        FileSystem.get(conf).delete(path, true);
+      } catch (IOException e) {
+        LOG.error(StringUtils.stringifyException(e));
+      }
+    }
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    // start the mini cluster if it is not running yet
+    if (!isMiniClusterRunning()) {
+      startMiniCluster();
+      Runtime.getRuntime().addShutdownHook(new MiniClusterShutdownThread());
+    }
+
+    // tell HttpClient to dump request and response headers into the test
+    // log at DEBUG level
+    Logger.getLogger("httpclient.wire.header").setLevel(Level.DEBUG);
+
+    super.setUp();
+  }
+}

Added: hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/Test00MiniCluster.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/Test00MiniCluster.java?rev=928876&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/Test00MiniCluster.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/Test00MiniCluster.java Mon Mar 29 19:15:15 2010
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009 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.stargate;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.client.HTable;
+
+public class Test00MiniCluster extends MiniClusterTestBase {
+  public void testDFSMiniCluster() {
+    assertNotNull(dfsCluster);
+  }
+
+  public void testZooKeeperMiniCluster() {
+    assertNotNull(zooKeeperCluster);
+  }
+
+  public void testHBaseMiniCluster() throws IOException {
+    assertNotNull(hbaseCluster);
+    assertNotNull(new HTable(conf, HConstants.META_TABLE_NAME));
+  }
+
+  public void testStargateServlet() throws IOException {
+    assertNotNull(server);
+  }
+}

Added: hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestRowResource.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestRowResource.java?rev=928876&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestRowResource.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestRowResource.java Mon Mar 29 19:15:15 2010
@@ -0,0 +1,383 @@
+/*
+ * 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.stargate;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URLEncoder;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.httpclient.Header;
+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.HBaseAdmin;
+import org.apache.hadoop.hbase.stargate.client.Client;
+import org.apache.hadoop.hbase.stargate.client.Cluster;
+import org.apache.hadoop.hbase.stargate.client.Response;
+import org.apache.hadoop.hbase.stargate.model.CellModel;
+import org.apache.hadoop.hbase.stargate.model.CellSetModel;
+import org.apache.hadoop.hbase.stargate.model.RowModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestRowResource extends MiniClusterTestBase {
+  private static final String TABLE = "TestRowResource";
+  private static final String COLUMN_1 = "a:";
+  private static final String COLUMN_2 = "b:";
+  private static final String ROW_1 = "testrow1";
+  private static final String VALUE_1 = "testvalue1";
+  private static final String ROW_2 = "testrow2";
+  private static final String VALUE_2 = "testvalue2";
+  private static final String ROW_3 = "testrow3";
+  private static final String VALUE_3 = "testvalue3";
+  private static final String ROW_4 = "testrow4";
+  private static final String VALUE_4 = "testvalue4";
+
+  private Client client;
+  private JAXBContext context;
+  private Marshaller marshaller;
+  private Unmarshaller unmarshaller;
+  private HBaseAdmin admin;
+
+  public TestRowResource() throws JAXBException {
+    super();
+    context = JAXBContext.newInstance(
+        CellModel.class,
+        CellSetModel.class,
+        RowModel.class);
+    marshaller = context.createMarshaller();
+    unmarshaller = context.createUnmarshaller();
+  }
+
+  @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_1))[0]));
+    htd.addFamily(new HColumnDescriptor(KeyValue.parseColumn(
+        Bytes.toBytes(COLUMN_2))[0]));
+    admin.createTable(htd);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    client.shutdown();
+    super.tearDown();
+  }
+
+  private Response deleteRow(String table, String row) throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    Response response = client.delete(path.toString());
+    Thread.yield();
+    return response;
+  }
+
+  private Response deleteValue(String table, String row, String column)
+      throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    Response response = client.delete(path.toString());
+    Thread.yield();
+    return response;
+  }
+
+  private Response getValueXML(String table, String row, String column)
+      throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    Response response = client.get(path.toString(), MIMETYPE_XML);
+    return response;
+  }
+
+  private Response getValuePB(String table, String row, String column) 
+      throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    Response response = client.get(path.toString(), MIMETYPE_PROTOBUF); 
+    return response;
+  }
+
+  private Response putValueXML(String table, String row, String column,
+      String value) throws IOException, JAXBException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes.toBytes(value)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(cellSetModel, writer);
+    Response response = client.put(path.toString(), MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    Thread.yield();
+    return response;
+  }
+
+  private void checkValueXML(String table, String row, String column, 
+      String value) throws IOException, JAXBException {
+    Response response = getValueXML(table, row, column);
+    assertEquals(response.getCode(), 200);
+    CellSetModel cellSet = (CellSetModel)
+      unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+    RowModel rowModel = cellSet.getRows().get(0);
+    CellModel cell = rowModel.getCells().get(0);
+    assertEquals(Bytes.toString(cell.getColumn()), column);
+    assertEquals(Bytes.toString(cell.getValue()), value);
+  }
+
+  private Response putValuePB(String table, String row, String column,
+      String value) throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes.toBytes(value)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    Response response = client.put(path.toString(), MIMETYPE_PROTOBUF,
+      cellSetModel.createProtobufOutput());
+    Thread.yield();
+    return response;
+  }
+
+  private void checkValuePB(String table, String row, String column, 
+      String value) throws IOException {
+    Response response = getValuePB(table, row, column);
+    assertEquals(response.getCode(), 200);
+    CellSetModel cellSet = new CellSetModel();
+    cellSet.getObjectFromMessage(response.getBody());
+    RowModel rowModel = cellSet.getRows().get(0);
+    CellModel cell = rowModel.getCells().get(0);
+    assertEquals(Bytes.toString(cell.getColumn()), column);
+    assertEquals(Bytes.toString(cell.getValue()), value);
+  }
+
+  public void testDelete() throws IOException, JAXBException {
+    Response response;
+    
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    response = putValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+
+    response = deleteValue(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 200);
+    response = getValueXML(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+    checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);    
+    response = getValueXML(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+    response = getValueXML(TABLE, ROW_1, COLUMN_2);
+    assertEquals(response.getCode(), 404);
+  }
+
+  public void testSingleCellGetPutXML() throws IOException, JAXBException {
+    Response response = getValueXML(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);    
+  }
+
+  public void testSingleCellGetPutPB() throws IOException, JAXBException {
+    Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+
+    response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+
+    response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);    
+  }
+
+  public void testSingleCellGetPutBinary() throws IOException {
+    final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1;
+    final byte[] body = Bytes.toBytes(VALUE_3);
+    Response response = client.put(path, MIMETYPE_BINARY, body);
+    assertEquals(response.getCode(), 200);
+    Thread.yield();
+
+    response = client.get(path, MIMETYPE_BINARY);
+    assertEquals(response.getCode(), 200);
+    assertTrue(Bytes.equals(response.getBody(), body));
+    boolean foundTimestampHeader = false;
+    for (Header header: response.getHeaders()) {
+      if (header.getName().equals("X-Timestamp")) {
+        foundTimestampHeader = true;
+        break;
+      }
+    }
+    assertTrue(foundTimestampHeader);
+
+    response = deleteRow(TABLE, ROW_3);
+    assertEquals(response.getCode(), 200);
+  }
+
+  public void testSingleCellGetJSON() throws IOException, JAXBException {
+    final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
+    Response response = client.put(path, MIMETYPE_BINARY,
+      Bytes.toBytes(VALUE_4));
+    assertEquals(response.getCode(), 200);
+    Thread.yield();
+    response = client.get(path, MIMETYPE_JSON);
+    assertEquals(response.getCode(), 200);
+    response = deleteRow(TABLE, ROW_4);
+    assertEquals(response.getCode(), 200);
+  }
+
+  public void testURLEncodedKey() throws IOException, JAXBException {
+    String encodedKey = URLEncoder.encode("http://www.google.com/", 
+      HConstants.UTF8_ENCODING);
+    Response response;
+    response = putValueXML(TABLE, encodedKey, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    response = putValuePB(TABLE, encodedKey, COLUMN_2, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, encodedKey, COLUMN_1, VALUE_1);
+    checkValueXML(TABLE, encodedKey, COLUMN_2, VALUE_2);
+  }
+
+  public void testMultiCellGetPutXML() throws IOException, JAXBException {
+    String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
+
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2)));
+    cellSetModel.addRow(rowModel);
+    rowModel = new RowModel(ROW_2);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_3)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_4)));
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(cellSetModel, writer);
+    Response response = client.put(path, MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    Thread.yield();
+
+    // make sure the fake row was not actually created
+    response = client.get(path, MIMETYPE_XML);
+    assertEquals(response.getCode(), 404);
+
+    // check that all of the values were created
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+    checkValueXML(TABLE, ROW_2, COLUMN_1, VALUE_3);
+    checkValueXML(TABLE, ROW_2, COLUMN_2, VALUE_4);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);    
+    response = deleteRow(TABLE, ROW_2);
+    assertEquals(response.getCode(), 200);
+  }
+
+  public void testMultiCellGetPutPB() throws IOException {
+    String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
+
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2)));
+    cellSetModel.addRow(rowModel);
+    rowModel = new RowModel(ROW_2);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_3)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_4)));
+    cellSetModel.addRow(rowModel);
+    Response response = client.put(path, MIMETYPE_PROTOBUF,
+      cellSetModel.createProtobufOutput());
+    Thread.yield();
+
+    // make sure the fake row was not actually created
+    response = client.get(path, MIMETYPE_PROTOBUF);
+    assertEquals(response.getCode(), 404);
+
+    // check that all of the values were created
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
+    checkValuePB(TABLE, ROW_2, COLUMN_1, VALUE_3);
+    checkValuePB(TABLE, ROW_2, COLUMN_2, VALUE_4);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);    
+    response = deleteRow(TABLE, ROW_2);
+    assertEquals(response.getCode(), 200);
+  }
+}

Added: hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannerResource.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannerResource.java?rev=928876&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannerResource.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannerResource.java Mon Mar 29 19:15:15 2010
@@ -0,0 +1,275 @@
+/*
+ * 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.stargate;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Iterator;
+import java.util.Random;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.httpclient.Header;
+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.client.Put;
+import org.apache.hadoop.hbase.stargate.client.Client;
+import org.apache.hadoop.hbase.stargate.client.Cluster;
+import org.apache.hadoop.hbase.stargate.client.Response;
+import org.apache.hadoop.hbase.stargate.model.CellModel;
+import org.apache.hadoop.hbase.stargate.model.CellSetModel;
+import org.apache.hadoop.hbase.stargate.model.RowModel;
+import org.apache.hadoop.hbase.stargate.model.ScannerModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestScannerResource extends MiniClusterTestBase {
+  private static final String TABLE = "TestScannerResource";
+  private static final String COLUMN_1 = "a:";
+  private static final String COLUMN_2 = "b:";
+
+  private static int expectedRows1;
+  private static int expectedRows2;
+
+  private Client client;
+  private JAXBContext context;
+  private Marshaller marshaller;
+  private Unmarshaller unmarshaller;
+  private HBaseAdmin admin;
+
+  private int insertData(String tableName, String column, double prob)
+      throws IOException {
+    Random rng = new Random();
+    int count = 0;
+    HTable table = new HTable(conf, tableName);
+    byte[] k = new byte[3];
+    byte [][] famAndQf = KeyValue.parseColumn(Bytes.toBytes(column));
+    for (byte b1 = 'a'; b1 < 'z'; b1++) {
+      for (byte b2 = 'a'; b2 < 'z'; b2++) {
+        for (byte b3 = 'a'; b3 < 'z'; b3++) {
+          if (rng.nextDouble() < prob) {
+            k[0] = b1;
+            k[1] = b2;
+            k[2] = b3;
+            Put put = new Put(k);
+            if(famAndQf.length == 1) {
+              put.add(famAndQf[0], new byte[0], k);
+            } else {
+              put.add(famAndQf[0], famAndQf[1], k);
+            }
+            table.put(put);
+            count++;
+          }
+        }
+      }
+    }
+    table.flushCommits();
+    return count;
+  }
+
+  public TestScannerResource() 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));
+    admin = new HBaseAdmin(conf);
+    if (admin.tableExists(TABLE)) {
+      return;
+    }
+    HTableDescriptor htd = new HTableDescriptor(TABLE);
+    htd.addFamily(new HColumnDescriptor(KeyValue.parseColumn(
+        Bytes.toBytes(COLUMN_1))[0]));
+    htd.addFamily(new HColumnDescriptor(KeyValue.parseColumn(
+        Bytes.toBytes(COLUMN_2))[0]));
+    admin.createTable(htd);
+    expectedRows1 = insertData(TABLE, COLUMN_1, 1.0);
+    expectedRows2 = insertData(TABLE, COLUMN_2, 0.5);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    client.shutdown();
+    super.tearDown();
+  }
+
+  private int countCellSet(CellSetModel model) {
+    int count = 0;
+    Iterator<RowModel> rows = model.getRows().iterator();
+    while (rows.hasNext()) {
+      RowModel row = rows.next();
+      Iterator<CellModel> cells = row.getCells().iterator();
+      while (cells.hasNext()) {
+        cells.next();
+        count++;
+      }
+    }
+    return count;
+  }
+
+  public void testSimpleScannerXML() throws IOException, JAXBException {
+    final int BATCH_SIZE = 5;
+    // new scanner
+    ScannerModel model = new ScannerModel();
+    model.setBatch(BATCH_SIZE);
+    model.addColumn(Bytes.toBytes(COLUMN_1));
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(model, writer);
+    byte[] body = Bytes.toBytes(writer.toString());
+    Response response = client.put("/" + TABLE + "/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()));
+    // confirm batch size conformance
+    assertEquals(countCellSet(cellSet), BATCH_SIZE);
+
+    // delete the scanner
+    response = client.delete(scannerURI);
+    assertEquals(response.getCode(), 200);
+  }
+
+  public void testSimpleScannerPB() throws IOException {
+    final int BATCH_SIZE = 10;
+    // new scanner
+    ScannerModel model = new ScannerModel();
+    model.setBatch(BATCH_SIZE);
+    model.addColumn(Bytes.toBytes(COLUMN_1));
+    Response response = client.put("/" + TABLE + "/scanner",
+      MIMETYPE_PROTOBUF, model.createProtobufOutput());
+    assertEquals(response.getCode(), 201);
+    String scannerURI = response.getLocation();
+    assertNotNull(scannerURI);
+
+    // get a cell set
+    response = client.get(scannerURI, MIMETYPE_PROTOBUF);
+    assertEquals(response.getCode(), 200);
+    CellSetModel cellSet = new CellSetModel();
+    cellSet.getObjectFromMessage(response.getBody());
+    // confirm batch size conformance
+    assertEquals(countCellSet(cellSet), BATCH_SIZE);
+
+    // delete the scanner
+    response = client.delete(scannerURI);
+    assertEquals(response.getCode(), 200);
+  }
+
+  public void testSimpleScannerBinary() throws IOException {
+    // new scanner
+    ScannerModel model = new ScannerModel();
+    model.setBatch(1);
+    model.addColumn(Bytes.toBytes(COLUMN_1));
+    Response response = client.put("/" + TABLE + "/scanner",
+      MIMETYPE_PROTOBUF, model.createProtobufOutput());
+    assertEquals(response.getCode(), 201);
+    String scannerURI = response.getLocation();
+    assertNotNull(scannerURI);
+
+    // get a cell
+    response = client.get(scannerURI, MIMETYPE_BINARY);
+    assertEquals(response.getCode(), 200);
+    // verify that data was returned
+    assertTrue(response.getBody().length > 0);
+    // verify that the expected X-headers are present
+    boolean foundRowHeader = false, foundColumnHeader = false,
+      foundTimestampHeader = false;
+    for (Header header: response.getHeaders()) {
+      if (header.getName().equals("X-Row")) {
+        foundRowHeader = true;
+      } else if (header.getName().equals("X-Column")) {
+        foundColumnHeader = true;
+      } else if (header.getName().equals("X-Timestamp")) {
+        foundTimestampHeader = true;
+      }
+    }
+    assertTrue(foundRowHeader);
+    assertTrue(foundColumnHeader);
+    assertTrue(foundTimestampHeader);
+
+    // delete the scanner
+    response = client.delete(scannerURI);
+    assertEquals(response.getCode(), 200);
+  }
+
+  private int fullTableScan(ScannerModel model) throws IOException {
+    model.setBatch(100);
+    Response response = client.put("/" + TABLE + "/scanner",
+        MIMETYPE_PROTOBUF, model.createProtobufOutput());
+    assertEquals(response.getCode(), 201);
+    String scannerURI = response.getLocation();
+    assertNotNull(scannerURI);
+    int count = 0;
+    while (true) {
+      response = client.get(scannerURI, MIMETYPE_PROTOBUF);
+      assertTrue(response.getCode() == 200 || response.getCode() == 204);
+      if (response.getCode() == 200) {
+        CellSetModel cellSet = new CellSetModel();
+        cellSet.getObjectFromMessage(response.getBody());
+        Iterator<RowModel> rows = cellSet.getRows().iterator();
+        while (rows.hasNext()) {
+          RowModel row = rows.next();
+          Iterator<CellModel> cells = row.getCells().iterator();
+          while (cells.hasNext()) {
+            cells.next();
+            count++;
+          }
+        }
+      } else {
+        break;
+      }
+    }
+    // delete the scanner
+    response = client.delete(scannerURI);
+    assertEquals(response.getCode(), 200);
+    return count;
+  }
+
+  public void testFullTableScan() throws IOException {
+    ScannerModel model = new ScannerModel();
+    model.addColumn(Bytes.toBytes(COLUMN_1));
+    assertEquals(fullTableScan(model), expectedRows1);
+
+    model = new ScannerModel();
+    model.addColumn(Bytes.toBytes(COLUMN_2));
+    assertEquals(fullTableScan(model), expectedRows2);
+  }
+}

Added: hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java?rev=928876&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java Mon Mar 29 19:15:15 2010
@@ -0,0 +1,979 @@
+/*
+ * 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.stargate;
+
+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.stargate.client.Client;
+import org.apache.hadoop.hbase.stargate.client.Cluster;
+import org.apache.hadoop.hbase.stargate.client.Response;
+import org.apache.hadoop.hbase.stargate.model.CellModel;
+import org.apache.hadoop.hbase.stargate.model.CellSetModel;
+import org.apache.hadoop.hbase.stargate.model.RowModel;
+import org.apache.hadoop.hbase.stargate.model.ScannerModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestScannersWithFilters extends MiniClusterTestBase {
+
+  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/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestSchemaResource.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestSchemaResource.java?rev=928876&view=auto
==============================================================================
--- hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestSchemaResource.java (added)
+++ hadoop/hbase/trunk/contrib/stargate/core/src/test/java/org/apache/hadoop/hbase/stargate/TestSchemaResource.java Mon Mar 29 19:15:15 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.stargate;
+
+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.stargate.client.Client;
+import org.apache.hadoop.hbase.stargate.client.Cluster;
+import org.apache.hadoop.hbase.stargate.client.Response;
+import org.apache.hadoop.hbase.stargate.model.ColumnSchemaModel;
+import org.apache.hadoop.hbase.stargate.model.TableSchemaModel;
+import org.apache.hadoop.hbase.stargate.model.TestTableSchemaModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestSchemaResource extends MiniClusterTestBase {
+  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));
+  }
+}



Mime
View raw message