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.HBaseTestingUtil; 034import org.apache.hadoop.hbase.HRegionLocation; 035import org.apache.hadoop.hbase.ServerName; 036import org.apache.hadoop.hbase.TableName; 037import org.apache.hadoop.hbase.client.Connection; 038import org.apache.hadoop.hbase.client.Durability; 039import org.apache.hadoop.hbase.client.Put; 040import org.apache.hadoop.hbase.client.RegionInfo; 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 HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 077 private static final HBaseRESTTestingUtility REST_TEST_UTIL = new HBaseRESTTestingUtility(); 078 private static Client client; 079 private static JAXBContext context; 080 081 @BeforeClass 082 public static void setUpBeforeClass() throws Exception { 083 TEST_UTIL.startMiniCluster(3); 084 REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration()); 085 client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort())); 086 context = JAXBContext.newInstance(TableModel.class, TableInfoModel.class, TableListModel.class, 087 TableRegionModel.class); 088 TEST_UTIL.createMultiRegionTable(TABLE, Bytes.toBytes(COLUMN_FAMILY), NUM_REGIONS); 089 byte[] k = new byte[3]; 090 byte[][] famAndQf = CellUtil.parseColumn(Bytes.toBytes(COLUMN)); 091 List<Put> puts = new ArrayList<>(); 092 for (byte b1 = 'a'; b1 < 'z'; b1++) { 093 for (byte b2 = 'a'; b2 < 'z'; b2++) { 094 for (byte b3 = 'a'; b3 < 'z'; b3++) { 095 k[0] = b1; 096 k[1] = b2; 097 k[2] = b3; 098 Put put = new Put(k); 099 put.setDurability(Durability.SKIP_WAL); 100 put.addColumn(famAndQf[0], famAndQf[1], k); 101 puts.add(put); 102 } 103 } 104 } 105 106 Connection connection = TEST_UTIL.getConnection(); 107 108 Table table = connection.getTable(TABLE); 109 table.put(puts); 110 table.close(); 111 112 RegionLocator regionLocator = connection.getRegionLocator(TABLE); 113 List<HRegionLocation> m = regionLocator.getAllRegionLocations(); 114 115 // should have four regions now 116 assertEquals(NUM_REGIONS, m.size()); 117 regionMap = m; 118 LOG.error("regions: " + regionMap); 119 regionLocator.close(); 120 } 121 122 @AfterClass 123 public static void tearDownAfterClass() throws Exception { 124 REST_TEST_UTIL.shutdownServletContainer(); 125 TEST_UTIL.shutdownMiniCluster(); 126 } 127 128 private static void checkTableList(TableListModel model) { 129 boolean found = false; 130 Iterator<TableModel> tables = model.getTables().iterator(); 131 assertTrue(tables.hasNext()); 132 while (tables.hasNext()) { 133 TableModel table = tables.next(); 134 if (table.getName().equals(TABLE.getNameAsString())) { 135 found = true; 136 break; 137 } 138 } 139 assertTrue(found); 140 } 141 142 void checkTableInfo(TableInfoModel model) { 143 assertEquals(model.getName(), TABLE.getNameAsString()); 144 Iterator<TableRegionModel> regions = model.getRegions().iterator(); 145 assertTrue(regions.hasNext()); 146 while (regions.hasNext()) { 147 TableRegionModel region = regions.next(); 148 boolean found = false; 149 LOG.debug("looking for region " + region.getName()); 150 for (HRegionLocation e : regionMap) { 151 RegionInfo hri = e.getRegion(); 152 // getRegionNameAsString uses Bytes.toStringBinary which escapes some non-printable 153 // characters 154 String hriRegionName = Bytes.toString(hri.getRegionName()); 155 String regionName = region.getName(); 156 LOG.debug("comparing to region " + hriRegionName); 157 if (hriRegionName.equals(regionName)) { 158 found = true; 159 byte[] startKey = hri.getStartKey(); 160 byte[] endKey = hri.getEndKey(); 161 ServerName serverName = e.getServerName(); 162 InetSocketAddress sa = 163 new InetSocketAddress(serverName.getHostname(), serverName.getPort()); 164 String location = sa.getHostName() + ":" + Integer.valueOf(sa.getPort()); 165 assertEquals(hri.getRegionId(), region.getId()); 166 assertTrue(Bytes.equals(startKey, region.getStartKey())); 167 assertTrue(Bytes.equals(endKey, region.getEndKey())); 168 assertEquals(location, region.getLocation()); 169 break; 170 } 171 } 172 assertTrue("Couldn't find region " + region.getName(), found); 173 } 174 } 175 176 @Test 177 public void testTableListText() throws IOException { 178 Response response = client.get("/", Constants.MIMETYPE_TEXT); 179 assertEquals(200, response.getCode()); 180 assertEquals(Constants.MIMETYPE_TEXT, response.getHeader("content-type")); 181 } 182 183 @Test 184 public void testTableListXML() throws IOException, JAXBException { 185 Response response = client.get("/", Constants.MIMETYPE_XML); 186 assertEquals(200, response.getCode()); 187 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 188 TableListModel model = (TableListModel) context.createUnmarshaller() 189 .unmarshal(new ByteArrayInputStream(response.getBody())); 190 checkTableList(model); 191 } 192 193 @Test 194 public void testTableListJSON() throws IOException { 195 Response response = client.get("/", Constants.MIMETYPE_JSON); 196 assertEquals(200, response.getCode()); 197 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 198 } 199 200 @Test 201 public void testTableListPB() throws IOException, JAXBException { 202 Response response = client.get("/", Constants.MIMETYPE_PROTOBUF); 203 assertEquals(200, response.getCode()); 204 assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type")); 205 TableListModel model = new TableListModel(); 206 model.getObjectFromMessage(response.getBody()); 207 checkTableList(model); 208 response = client.get("/", Constants.MIMETYPE_PROTOBUF_IETF); 209 assertEquals(200, response.getCode()); 210 assertEquals(Constants.MIMETYPE_PROTOBUF_IETF, response.getHeader("content-type")); 211 model = new TableListModel(); 212 model.getObjectFromMessage(response.getBody()); 213 checkTableList(model); 214 } 215 216 @Test 217 public void testTableInfoText() throws IOException { 218 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_TEXT); 219 assertEquals(200, response.getCode()); 220 assertEquals(Constants.MIMETYPE_TEXT, response.getHeader("content-type")); 221 } 222 223 @Test 224 public void testTableInfoXML() throws IOException, JAXBException { 225 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_XML); 226 assertEquals(200, response.getCode()); 227 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 228 TableInfoModel model = (TableInfoModel) context.createUnmarshaller() 229 .unmarshal(new ByteArrayInputStream(response.getBody())); 230 checkTableInfo(model); 231 } 232 233 @Test 234 public void testTableInfoJSON() throws IOException { 235 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_JSON); 236 assertEquals(200, response.getCode()); 237 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 238 } 239 240 @Test 241 public void testTableInfoPB() throws IOException, JAXBException { 242 Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_PROTOBUF); 243 assertEquals(200, response.getCode()); 244 assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type")); 245 TableInfoModel model = new TableInfoModel(); 246 model.getObjectFromMessage(response.getBody()); 247 checkTableInfo(model); 248 response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_PROTOBUF_IETF); 249 assertEquals(200, response.getCode()); 250 assertEquals(Constants.MIMETYPE_PROTOBUF_IETF, response.getHeader("content-type")); 251 model = new TableInfoModel(); 252 model.getObjectFromMessage(response.getBody()); 253 checkTableInfo(model); 254 } 255 256 @Test 257 public void testTableNotFound() throws IOException { 258 String notExistTable = "notexist"; 259 Response response1 = client.get("/" + notExistTable + "/schema", Constants.MIMETYPE_JSON); 260 assertEquals(404, response1.getCode()); 261 Response response2 = client.get("/" + notExistTable + "/regions", Constants.MIMETYPE_XML); 262 assertEquals(404, response2.getCode()); 263 } 264 265}