001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.rest; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertTrue; 022 023import java.io.ByteArrayInputStream; 024import java.io.IOException; 025import java.net.InetSocketAddress; 026import java.util.ArrayList; 027import java.util.Iterator; 028import java.util.List; 029import javax.xml.bind.JAXBContext; 030import javax.xml.bind.JAXBException; 031import org.apache.hadoop.hbase.CellUtil; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HBaseTestingUtility; 034import org.apache.hadoop.hbase.HRegionInfo; 035import org.apache.hadoop.hbase.HRegionLocation; 036import org.apache.hadoop.hbase.ServerName; 037import org.apache.hadoop.hbase.TableName; 038import org.apache.hadoop.hbase.client.Connection; 039import org.apache.hadoop.hbase.client.Durability; 040import org.apache.hadoop.hbase.client.Put; 041import org.apache.hadoop.hbase.client.RegionLocator; 042import org.apache.hadoop.hbase.client.Table; 043import org.apache.hadoop.hbase.rest.client.Client; 044import org.apache.hadoop.hbase.rest.client.Cluster; 045import org.apache.hadoop.hbase.rest.client.Response; 046import org.apache.hadoop.hbase.rest.model.TableInfoModel; 047import org.apache.hadoop.hbase.rest.model.TableListModel; 048import org.apache.hadoop.hbase.rest.model.TableModel; 049import org.apache.hadoop.hbase.rest.model.TableRegionModel; 050import org.apache.hadoop.hbase.testclassification.MediumTests; 051import org.apache.hadoop.hbase.testclassification.RestTests; 052import org.apache.hadoop.hbase.util.Bytes; 053import org.junit.AfterClass; 054import org.junit.BeforeClass; 055import org.junit.ClassRule; 056import org.junit.Test; 057import org.junit.experimental.categories.Category; 058import org.slf4j.Logger; 059import org.slf4j.LoggerFactory; 060 061@Category({RestTests.class, MediumTests.class}) 062public class TestTableResource { 063 064 @ClassRule 065 public static final HBaseClassTestRule CLASS_RULE = 066 HBaseClassTestRule.forClass(TestTableResource.class); 067 068 private static final Logger LOG = LoggerFactory.getLogger(TestTableResource.class); 069 070 private static final TableName TABLE = TableName.valueOf("TestTableResource"); 071 private static final String COLUMN_FAMILY = "test"; 072 private static final String COLUMN = COLUMN_FAMILY + ":qualifier"; 073 private static final int NUM_REGIONS = 4; 074 private static List<HRegionLocation> regionMap; 075 076 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 077 private static final HBaseRESTTestingUtility REST_TEST_UTIL = 078 new HBaseRESTTestingUtility(); 079 private static Client client; 080 private static JAXBContext context; 081 082 @BeforeClass 083 public static void setUpBeforeClass() throws Exception { 084 TEST_UTIL.startMiniCluster(3); 085 REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration()); 086 client = new Client(new Cluster().add("localhost", 087 REST_TEST_UTIL.getServletPort())); 088 context = JAXBContext.newInstance( 089 TableModel.class, 090 TableInfoModel.class, 091 TableListModel.class, 092 TableRegionModel.class); 093 TEST_UTIL.createMultiRegionTable(TABLE, Bytes.toBytes(COLUMN_FAMILY), NUM_REGIONS); 094 byte[] k = new byte[3]; 095 byte [][] famAndQf = CellUtil.parseColumn(Bytes.toBytes(COLUMN)); 096 List<Put> puts = new ArrayList<>(); 097 for (byte b1 = 'a'; b1 < 'z'; b1++) { 098 for (byte b2 = 'a'; b2 < 'z'; b2++) { 099 for (byte b3 = 'a'; b3 < 'z'; b3++) { 100 k[0] = b1; 101 k[1] = b2; 102 k[2] = b3; 103 Put put = new Put(k); 104 put.setDurability(Durability.SKIP_WAL); 105 put.addColumn(famAndQf[0], famAndQf[1], k); 106 puts.add(put); 107 } 108 } 109 } 110 111 Connection connection = TEST_UTIL.getConnection(); 112 113 Table table = connection.getTable(TABLE); 114 table.put(puts); 115 table.close(); 116 117 RegionLocator regionLocator = connection.getRegionLocator(TABLE); 118 List<HRegionLocation> m = regionLocator.getAllRegionLocations(); 119 120 // should have four regions now 121 assertEquals(NUM_REGIONS, m.size()); 122 regionMap = m; 123 LOG.error("regions: " + regionMap); 124 regionLocator.close(); 125 } 126 127 @AfterClass 128 public static void tearDownAfterClass() throws Exception { 129 REST_TEST_UTIL.shutdownServletContainer(); 130 TEST_UTIL.shutdownMiniCluster(); 131 } 132 133 private static void checkTableList(TableListModel model) { 134 boolean found = false; 135 Iterator<TableModel> tables = model.getTables().iterator(); 136 assertTrue(tables.hasNext()); 137 while (tables.hasNext()) { 138 TableModel table = tables.next(); 139 if (table.getName().equals(TABLE.getNameAsString())) { 140 found = true; 141 break; 142 } 143 } 144 assertTrue(found); 145 } 146 147 void checkTableInfo(TableInfoModel model) { 148 assertEquals(model.getName(), TABLE.getNameAsString()); 149 Iterator<TableRegionModel> regions = model.getRegions().iterator(); 150 assertTrue(regions.hasNext()); 151 while (regions.hasNext()) { 152 TableRegionModel region = regions.next(); 153 boolean found = false; 154 LOG.debug("looking for region " + region.getName()); 155 for (HRegionLocation e: regionMap) { 156 HRegionInfo hri = e.getRegionInfo(); 157 // getRegionNameAsString uses Bytes.toStringBinary which escapes some non-printable 158 // characters 159 String hriRegionName = Bytes.toString(hri.getRegionName()); 160 String regionName = region.getName(); 161 LOG.debug("comparing to region " + hriRegionName); 162 if (hriRegionName.equals(regionName)) { 163 found = true; 164 byte[] startKey = hri.getStartKey(); 165 byte[] endKey = hri.getEndKey(); 166 ServerName serverName = e.getServerName(); 167 InetSocketAddress sa = 168 new InetSocketAddress(serverName.getHostname(), serverName.getPort()); 169 String location = sa.getHostName() + ":" + 170 Integer.valueOf(sa.getPort()); 171 assertEquals(hri.getRegionId(), region.getId()); 172 assertTrue(Bytes.equals(startKey, region.getStartKey())); 173 assertTrue(Bytes.equals(endKey, region.getEndKey())); 174 assertEquals(location, region.getLocation()); 175 break; 176 } 177 } 178 assertTrue("Couldn't find region " + region.getName(), found); 179 } 180 } 181 182 @Test 183 public void testTableListText() throws IOException { 184 Response response = client.get("/", Constants.MIMETYPE_TEXT); 185 assertEquals(200, response.getCode()); 186 assertEquals(Constants.MIMETYPE_TEXT, response.getHeader("content-type")); 187 } 188 189 @Test 190 public void testTableListXML() throws IOException, JAXBException { 191 Response response = client.get("/", Constants.MIMETYPE_XML); 192 assertEquals(200, response.getCode()); 193 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 194 TableListModel model = (TableListModel) 195 context.createUnmarshaller() 196 .unmarshal(new ByteArrayInputStream(response.getBody())); 197 checkTableList(model); 198 } 199 200 @Test 201 public void testTableListJSON() throws IOException { 202 Response response = client.get("/", Constants.MIMETYPE_JSON); 203 assertEquals(200, response.getCode()); 204 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 205 } 206 207 @Test 208 public void testTableListPB() throws IOException, JAXBException { 209 Response response = client.get("/", Constants.MIMETYPE_PROTOBUF); 210 assertEquals(200, response.getCode()); 211 assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type")); 212 TableListModel model = new TableListModel(); 213 model.getObjectFromMessage(response.getBody()); 214 checkTableList(model); 215 response = client.get("/", Constants.MIMETYPE_PROTOBUF_IETF); 216 assertEquals(200, response.getCode()); 217 assertEquals(Constants.MIMETYPE_PROTOBUF_IETF, response.getHeader("content-type")); 218 model = new TableListModel(); 219 model.getObjectFromMessage(response.getBody()); 220 checkTableList(model); 221 } 222 223 @Test 224 public void testTableInfoText() throws IOException { 225 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_TEXT); 226 assertEquals(200, response.getCode()); 227 assertEquals(Constants.MIMETYPE_TEXT, response.getHeader("content-type")); 228 } 229 230 @Test 231 public void testTableInfoXML() throws IOException, JAXBException { 232 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_XML); 233 assertEquals(200, response.getCode()); 234 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 235 TableInfoModel model = (TableInfoModel) 236 context.createUnmarshaller() 237 .unmarshal(new ByteArrayInputStream(response.getBody())); 238 checkTableInfo(model); 239 } 240 241 @Test 242 public void testTableInfoJSON() throws IOException { 243 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_JSON); 244 assertEquals(200, response.getCode()); 245 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 246 } 247 248 @Test 249 public void testTableInfoPB() throws IOException, JAXBException { 250 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_PROTOBUF); 251 assertEquals(200, response.getCode()); 252 assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type")); 253 TableInfoModel model = new TableInfoModel(); 254 model.getObjectFromMessage(response.getBody()); 255 checkTableInfo(model); 256 response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_PROTOBUF_IETF); 257 assertEquals(200, response.getCode()); 258 assertEquals(Constants.MIMETYPE_PROTOBUF_IETF, response.getHeader("content-type")); 259 model = new TableInfoModel(); 260 model.getObjectFromMessage(response.getBody()); 261 checkTableInfo(model); 262 } 263 264 @Test 265 public void testTableNotFound() throws IOException { 266 String notExistTable = "notexist"; 267 Response response1 = client.get("/" + notExistTable + "/schema", Constants.MIMETYPE_JSON); 268 assertEquals(404, response1.getCode()); 269 Response response2 = client.get("/" + notExistTable + "/regions", Constants.MIMETYPE_XML); 270 assertEquals(404, response2.getCode()); 271 } 272 273} 274