1   /*
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.rest;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.IOException;
25  import java.net.InetSocketAddress;
26  import java.util.Iterator;
27  import java.util.Map;
28  
29  import javax.xml.bind.JAXBContext;
30  import javax.xml.bind.JAXBException;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.hbase.HBaseTestingUtility;
35  import org.apache.hadoop.hbase.HColumnDescriptor;
36  import org.apache.hadoop.hbase.HRegionInfo;
37  import org.apache.hadoop.hbase.HServerAddress;
38  import org.apache.hadoop.hbase.HTableDescriptor;
39  import org.apache.hadoop.hbase.KeyValue;
40  import org.apache.hadoop.hbase.client.HBaseAdmin;
41  import org.apache.hadoop.hbase.client.HTable;
42  import org.apache.hadoop.hbase.client.Put;
43  import org.apache.hadoop.hbase.rest.client.Client;
44  import org.apache.hadoop.hbase.rest.client.Cluster;
45  import org.apache.hadoop.hbase.rest.client.Response;
46  import org.apache.hadoop.hbase.rest.model.TableModel;
47  import org.apache.hadoop.hbase.rest.model.TableInfoModel;
48  import org.apache.hadoop.hbase.rest.model.TableListModel;
49  import org.apache.hadoop.hbase.rest.model.TableRegionModel;
50  import org.apache.hadoop.hbase.util.Bytes;
51  import org.apache.hadoop.util.StringUtils;
52  
53  import static org.junit.Assert.*;
54  import org.junit.AfterClass;
55  import org.junit.BeforeClass;
56  import org.junit.Test;
57  
58  public class TestTableResource {
59    private static final Log LOG = LogFactory.getLog(TestTableResource.class);
60  
61    private static String TABLE = "TestTableResource";
62    private static String COLUMN_FAMILY = "test";
63    private static String COLUMN = COLUMN_FAMILY + ":qualifier";
64    private static Map<HRegionInfo,HServerAddress> regionMap;
65  
66    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
67    private static final HBaseRESTTestingUtility REST_TEST_UTIL = 
68      new HBaseRESTTestingUtility();
69    private static Client client;
70    private static JAXBContext context;
71  
72    @BeforeClass
73    public static void setUpBeforeClass() throws Exception {
74      TEST_UTIL.startMiniCluster(3);
75      REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
76      client = new Client(new Cluster().add("localhost", 
77        REST_TEST_UTIL.getServletPort()));
78      context = JAXBContext.newInstance(
79          TableModel.class,
80          TableInfoModel.class,
81          TableListModel.class,
82          TableRegionModel.class);
83      HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
84      if (admin.tableExists(TABLE)) {
85        return;
86      }
87      HTableDescriptor htd = new HTableDescriptor(TABLE);
88      htd.addFamily(new HColumnDescriptor(COLUMN_FAMILY));
89      admin.createTable(htd);
90      HTable table = new HTable(TEST_UTIL.getConfiguration(), TABLE);
91      byte[] k = new byte[3];
92      byte [][] famAndQf = KeyValue.parseColumn(Bytes.toBytes(COLUMN));
93      for (byte b1 = 'a'; b1 < 'z'; b1++) {
94        for (byte b2 = 'a'; b2 < 'z'; b2++) {
95          for (byte b3 = 'a'; b3 < 'z'; b3++) {
96            k[0] = b1;
97            k[1] = b2;
98            k[2] = b3;
99            Put put = new Put(k);
100           put.add(famAndQf[0], famAndQf[1], k);
101           table.put(put);
102         }
103       }
104     }
105     table.flushCommits();
106     // get the initial layout (should just be one region)
107     Map<HRegionInfo,HServerAddress> m = table.getRegionsInfo();
108     assertEquals(m.size(), 1);
109     // tell the master to split the table
110     admin.split(TABLE);
111     // give some time for the split to happen
112     try {
113       Thread.sleep(15 * 1000);
114     } catch (InterruptedException e) {
115       LOG.warn(StringUtils.stringifyException(e));
116     }
117     // check again
118     m = table.getRegionsInfo();
119     // should have two regions now
120     assertEquals(m.size(), 2);
121     regionMap = m;
122     LOG.info("regions: " + regionMap);
123   }
124 
125   @AfterClass
126   public static void tearDownAfterClass() throws Exception {
127     REST_TEST_UTIL.shutdownServletContainer();
128     TEST_UTIL.shutdownMiniCluster();
129   }
130 
131   private static void checkTableList(TableListModel model) {
132     boolean found = false;
133     Iterator<TableModel> tables = model.getTables().iterator();
134     assertTrue(tables.hasNext());
135     while (tables.hasNext()) {
136       TableModel table = tables.next();
137       if (table.getName().equals(TABLE)) {
138         found = true;
139         break;
140       }
141     }
142     assertTrue(found);
143   }
144 
145   void checkTableInfo(TableInfoModel model) {
146     assertEquals(model.getName(), TABLE);
147     Iterator<TableRegionModel> regions = model.getRegions().iterator();
148     assertTrue(regions.hasNext());
149     while (regions.hasNext()) {
150       TableRegionModel region = regions.next();
151       boolean found = false;
152       for (Map.Entry<HRegionInfo,HServerAddress> e: regionMap.entrySet()) {
153         HRegionInfo hri = e.getKey();
154         String hriRegionName = hri.getRegionNameAsString();
155         String regionName = region.getName();
156         if (hriRegionName.equals(regionName)) {
157           found = true;
158           byte[] startKey = hri.getStartKey();
159           byte[] endKey = hri.getEndKey();
160           InetSocketAddress sa = e.getValue().getInetSocketAddress();
161           String location = sa.getHostName() + ":" +
162             Integer.valueOf(sa.getPort());
163           assertEquals(hri.getRegionId(), region.getId());
164           assertTrue(Bytes.equals(startKey, region.getStartKey()));
165           assertTrue(Bytes.equals(endKey, region.getEndKey()));
166           assertEquals(location, region.getLocation());
167           break;
168         }
169       }
170       assertTrue(found);
171     }
172   }
173 
174   @Test
175   public void testTableListText() throws IOException {
176     Response response = client.get("/", Constants.MIMETYPE_TEXT);
177     assertEquals(response.getCode(), 200);
178   }
179 
180   @Test
181   public void testTableListXML() throws IOException, JAXBException {
182     Response response = client.get("/", Constants.MIMETYPE_XML);
183     assertEquals(response.getCode(), 200);
184     TableListModel model = (TableListModel)
185       context.createUnmarshaller()
186         .unmarshal(new ByteArrayInputStream(response.getBody()));
187     checkTableList(model);
188   }
189 
190   @Test
191   public void testTableListJSON() throws IOException {
192     Response response = client.get("/", Constants.MIMETYPE_JSON);
193     assertEquals(response.getCode(), 200);
194   }
195 
196   @Test
197   public void testTableListPB() throws IOException, JAXBException {
198     Response response = client.get("/", Constants.MIMETYPE_PROTOBUF);
199     assertEquals(response.getCode(), 200);
200     TableListModel model = new TableListModel();
201     model.getObjectFromMessage(response.getBody());
202     checkTableList(model);
203   }
204 
205   @Test
206   public void testTableInfoText() throws IOException {
207     Response response = client.get("/" + TABLE + "/regions",
208       Constants.MIMETYPE_TEXT);
209     assertEquals(response.getCode(), 200);
210   }
211 
212   @Test
213   public void testTableInfoXML() throws IOException, JAXBException {
214     Response response = client.get("/" + TABLE + "/regions", 
215       Constants.MIMETYPE_XML);
216     assertEquals(response.getCode(), 200);
217     TableInfoModel model = (TableInfoModel)
218       context.createUnmarshaller()
219         .unmarshal(new ByteArrayInputStream(response.getBody()));
220     checkTableInfo(model);
221   }
222 
223   @Test
224   public void testTableInfoJSON() throws IOException {
225     Response response = client.get("/" + TABLE + "/regions", 
226       Constants.MIMETYPE_JSON);
227     assertEquals(response.getCode(), 200);
228   }
229 
230   @Test
231   public void testTableInfoPB() throws IOException, JAXBException {
232     Response response = client.get("/" + TABLE + "/regions",
233       Constants.MIMETYPE_PROTOBUF);
234     assertEquals(response.getCode(), 200);
235     TableInfoModel model = new TableInfoModel();
236     model.getObjectFromMessage(response.getBody());
237     checkTableInfo(model);
238   }
239 }