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