View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.rest;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertTrue;
23  
24  import java.io.ByteArrayInputStream;
25  import java.io.IOException;
26  import java.io.StringWriter;
27  import java.net.URLEncoder;
28  import java.util.HashMap;
29  import java.util.List;
30  
31  import javax.xml.bind.JAXBException;
32  
33  import org.apache.commons.httpclient.Header;
34  import org.apache.hadoop.hbase.CompatibilityFactory;
35  import org.apache.hadoop.hbase.HConstants;
36  import org.apache.hadoop.hbase.testclassification.MediumTests;
37  import org.apache.hadoop.hbase.rest.client.Response;
38  import org.apache.hadoop.hbase.rest.model.CellModel;
39  import org.apache.hadoop.hbase.rest.model.CellSetModel;
40  import org.apache.hadoop.hbase.rest.model.RowModel;
41  import org.apache.hadoop.hbase.security.UserProvider;
42  import org.apache.hadoop.hbase.test.MetricsAssertHelper;
43  import org.apache.hadoop.hbase.util.Bytes;
44  import org.junit.Test;
45  import org.junit.experimental.categories.Category;
46  
47  @Category(MediumTests.class)
48  public class TestGetAndPutResource extends RowResourceBase {
49  
50    private static final MetricsAssertHelper METRICS_ASSERT =
51        CompatibilityFactory.getInstance(MetricsAssertHelper.class);
52  
53    @Test
54    public void testForbidden() throws IOException, JAXBException {
55      conf.set("hbase.rest.readonly", "true");
56  
57      Response response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
58      assertEquals(403, response.getCode());
59      response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
60      assertEquals(403, response.getCode());
61      response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2);
62      assertEquals(403, response.getCode());
63      response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2);
64      assertEquals(403, response.getCode());
65      response = deleteValue(TABLE, ROW_1, COLUMN_1);
66      assertEquals(403, response.getCode());
67      response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
68      assertEquals(403, response.getCode());
69      response = deleteRow(TABLE, ROW_1);
70      assertEquals(403, response.getCode());
71  
72      conf.set("hbase.rest.readonly", "false");
73  
74      response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
75      assertEquals(200, response.getCode());
76      response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
77      assertEquals(200, response.getCode());
78      response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2);
79      assertEquals(200, response.getCode());
80      response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3);
81      assertEquals(200, response.getCode());
82      response = deleteValue(TABLE, ROW_1, COLUMN_1);
83      assertEquals(200, response.getCode());
84      response = deleteRow(TABLE, ROW_1);
85      assertEquals(200, response.getCode());
86    }
87  
88    @Test
89    public void testSingleCellGetPutXML() throws IOException, JAXBException {
90      Response response = getValueXML(TABLE, ROW_1, COLUMN_1);
91      assertEquals(404, response.getCode());
92  
93      response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
94      assertEquals(200, response.getCode());
95      checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
96      response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
97      assertEquals(200, response.getCode());
98      checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
99      response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3);
100     assertEquals(200, response.getCode());
101     checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3);
102     response = checkAndDeleteXML(TABLE, ROW_1, COLUMN_1, VALUE_3);
103     assertEquals(200, response.getCode());
104 
105     response = deleteRow(TABLE, ROW_1);
106     assertEquals(200, response.getCode());
107   }
108 
109   @Test
110   public void testSingleCellGetPutPB() throws IOException, JAXBException {
111     Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
112     assertEquals(404, response.getCode());
113     
114     response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
115     assertEquals(200, response.getCode());
116     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
117     response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
118     assertEquals(200, response.getCode());
119     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2);
120 
121     response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3);
122     assertEquals(200, response.getCode());
123     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3);
124     response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3, VALUE_4);
125     assertEquals(200, response.getCode());
126     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_4);
127 
128     response = deleteRow(TABLE, ROW_1);
129     assertEquals(200, response.getCode());
130   }
131 
132   @Test
133   public void testMultipleCellCheckPutPB() throws IOException, JAXBException {
134     Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
135     assertEquals(404, response.getCode());
136 
137     // Add 2 Columns to setup the test
138     response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
139     assertEquals(200, response.getCode());
140     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
141 
142     response = putValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
143     assertEquals(200, response.getCode());
144     checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
145 
146     HashMap<String,String> otherCells = new HashMap<String, String>();
147     otherCells.put(COLUMN_2,VALUE_3);
148 
149     // On Success update both the cells
150     response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_3, otherCells);
151     assertEquals(200, response.getCode());
152     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3);
153     checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_3);
154 
155     // On Failure, we dont update any cells
156     response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_4, otherCells);
157     assertEquals(304, response.getCode());
158     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3);
159     checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_3);
160 
161     response = deleteRow(TABLE, ROW_1);
162     assertEquals(200, response.getCode());
163   }
164 
165   @Test
166   public void testMultipleCellCheckPutXML() throws IOException, JAXBException {
167     Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
168     assertEquals(404, response.getCode());
169 
170     // Add 2 Columns to setup the test
171     response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
172     assertEquals(200, response.getCode());
173     checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
174 
175     response = putValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
176     assertEquals(200, response.getCode());
177     checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
178 
179     HashMap<String,String> otherCells = new HashMap<String, String>();
180     otherCells.put(COLUMN_2,VALUE_3);
181 
182     // On Success update both the cells
183     response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_3, otherCells);
184     assertEquals(200, response.getCode());
185     checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3);
186     checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_3);
187 
188     // On Failure, we dont update any cells
189     response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_4, otherCells);
190     assertEquals(304, response.getCode());
191     checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3);
192     checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_3);
193 
194     response = deleteRow(TABLE, ROW_1);
195     assertEquals(200, response.getCode());
196   }
197 
198   @Test
199   public void testMultipleCellCheckDeletePB() throws IOException, JAXBException {
200     Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
201     assertEquals(404, response.getCode());
202 
203     // Add 3 Columns to setup the test
204     response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
205     assertEquals(200, response.getCode());
206     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
207 
208     response = putValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
209     assertEquals(200, response.getCode());
210     checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
211 
212     response = putValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3);
213     assertEquals(200, response.getCode());
214     checkValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3);
215 
216     // Deletes the following columns based on Column1 check
217     HashMap<String,String> cellsToDelete = new HashMap<String, String>();
218     cellsToDelete.put(COLUMN_2,VALUE_2); // Value does not matter
219     cellsToDelete.put(COLUMN_3,VALUE_3); // Value does not matter
220 
221     // On Success update both the cells
222     response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_1, cellsToDelete);
223     assertEquals(200, response.getCode());
224 
225     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
226 
227     response = getValuePB(TABLE, ROW_1, COLUMN_2);
228     assertEquals(404, response.getCode());
229 
230     response = getValuePB(TABLE, ROW_1, COLUMN_3);
231     assertEquals(404, response.getCode());
232 
233     response = putValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
234     assertEquals(200, response.getCode());
235     checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
236 
237     response = putValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3);
238     assertEquals(200, response.getCode());
239     checkValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3);
240 
241     // On Failure, we dont update any cells
242     response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_3, cellsToDelete);
243     assertEquals(304, response.getCode());
244     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
245     checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
246     checkValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3);
247 
248     response = deleteRow(TABLE, ROW_1);
249     assertEquals(200, response.getCode());
250   }
251 
252  @Test
253   public void testSingleCellGetPutBinary() throws IOException {
254     final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1;
255     final byte[] body = Bytes.toBytes(VALUE_3);
256     Response response = client.put(path, Constants.MIMETYPE_BINARY, body);
257     assertEquals(200, response.getCode());
258     Thread.yield();
259 
260     response = client.get(path, Constants.MIMETYPE_BINARY);
261     assertEquals(200, response.getCode());
262     assertEquals(Constants.MIMETYPE_BINARY, response.getHeader("content-type"));
263     assertTrue(Bytes.equals(response.getBody(), body));
264     boolean foundTimestampHeader = false;
265     for (Header header: response.getHeaders()) {
266       if (header.getName().equals("X-Timestamp")) {
267         foundTimestampHeader = true;
268         break;
269       }
270     }
271     assertTrue(foundTimestampHeader);
272 
273     response = deleteRow(TABLE, ROW_3);
274     assertEquals(200, response.getCode());
275   }
276 
277   @Test
278   public void testSingleCellGetJSON() throws IOException, JAXBException {
279     final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
280     Response response = client.put(path, Constants.MIMETYPE_BINARY,
281       Bytes.toBytes(VALUE_4));
282     assertEquals(200, response.getCode());
283     Thread.yield();
284     response = client.get(path, Constants.MIMETYPE_JSON);
285     assertEquals(200, response.getCode());
286     assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
287     response = deleteRow(TABLE, ROW_4);
288     assertEquals(200, response.getCode());
289   }
290 
291   @Test
292   public void testLatestCellGetJSON() throws IOException, JAXBException {
293     final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
294     CellSetModel cellSetModel = new CellSetModel();
295     RowModel rowModel = new RowModel(ROW_4);
296     CellModel cellOne = new CellModel(Bytes.toBytes(COLUMN_1), 1L,
297       Bytes.toBytes(VALUE_1));
298     CellModel cellTwo = new CellModel(Bytes.toBytes(COLUMN_1), 2L,
299       Bytes.toBytes(VALUE_2));
300     rowModel.addCell(cellOne);
301     rowModel.addCell(cellTwo);
302     cellSetModel.addRow(rowModel);
303     String jsonString = jsonMapper.writeValueAsString(cellSetModel);
304     Response response = client.put(path, Constants.MIMETYPE_JSON,
305       Bytes.toBytes(jsonString));
306     assertEquals(200, response.getCode());
307     Thread.yield();
308     response = client.get(path, Constants.MIMETYPE_JSON);
309     assertEquals(200, response.getCode());
310     assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
311     CellSetModel cellSet = jsonMapper.readValue(response.getBody(), CellSetModel.class);
312     assertTrue(cellSet.getRows().size() == 1);
313     assertTrue(cellSet.getRows().get(0).getCells().size() == 1);
314     CellModel cell = cellSet.getRows().get(0).getCells().get(0);
315     assertEquals(VALUE_2 , Bytes.toString(cell.getValue()));
316     assertEquals(2L , cell.getTimestamp());
317     response = deleteRow(TABLE, ROW_4);
318     assertEquals(200, response.getCode());
319   }
320 
321   @Test
322   public void testURLEncodedKey() throws IOException, JAXBException {
323     String urlKey = "http://example.com/foo";
324     StringBuilder path = new StringBuilder();
325     path.append('/');
326     path.append(TABLE);
327     path.append('/');
328     path.append(URLEncoder.encode(urlKey, HConstants.UTF8_ENCODING));
329     path.append('/');
330     path.append(COLUMN_1);
331     Response response;
332     response = putValueXML(path.toString(), TABLE, urlKey, COLUMN_1,
333       VALUE_1);
334     assertEquals(200, response.getCode());
335     checkValueXML(path.toString(), TABLE, urlKey, COLUMN_1, VALUE_1);
336   }
337 
338   @Test
339   public void testNoSuchCF() throws IOException, JAXBException {
340     final String goodPath = "/" + TABLE + "/" + ROW_1 + "/" + CFA+":";
341     final String badPath = "/" + TABLE + "/" + ROW_1 + "/" + "BAD";
342     Response response = client.post(goodPath, Constants.MIMETYPE_BINARY,
343       Bytes.toBytes(VALUE_1));
344     assertEquals(200, response.getCode());
345     assertEquals(200, client.get(goodPath, Constants.MIMETYPE_BINARY).getCode());
346     assertEquals(404, client.get(badPath, Constants.MIMETYPE_BINARY).getCode());
347     assertEquals(200, client.get(goodPath, Constants.MIMETYPE_BINARY).getCode());
348   }
349 
350   @Test
351   public void testMultiCellGetPutXML() throws IOException, JAXBException {
352     String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
353 
354     CellSetModel cellSetModel = new CellSetModel();
355     RowModel rowModel = new RowModel(ROW_1);
356     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
357       Bytes.toBytes(VALUE_1)));
358     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
359       Bytes.toBytes(VALUE_2)));
360     cellSetModel.addRow(rowModel);
361     rowModel = new RowModel(ROW_2);
362     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
363       Bytes.toBytes(VALUE_3)));
364     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
365       Bytes.toBytes(VALUE_4)));
366     cellSetModel.addRow(rowModel);
367     StringWriter writer = new StringWriter();
368     xmlMarshaller.marshal(cellSetModel, writer);
369     Response response = client.put(path, Constants.MIMETYPE_XML,
370       Bytes.toBytes(writer.toString()));
371     Thread.yield();
372 
373     // make sure the fake row was not actually created
374     response = client.get(path, Constants.MIMETYPE_XML);
375     assertEquals(404, response.getCode());
376 
377     // check that all of the values were created
378     checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
379     checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
380     checkValueXML(TABLE, ROW_2, COLUMN_1, VALUE_3);
381     checkValueXML(TABLE, ROW_2, COLUMN_2, VALUE_4);
382 
383     response = deleteRow(TABLE, ROW_1);
384     assertEquals(200, response.getCode());
385     response = deleteRow(TABLE, ROW_2);
386     assertEquals(200, response.getCode());
387   }
388 
389   @Test
390   public void testMultiCellGetPutPB() throws IOException {
391     String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
392 
393     CellSetModel cellSetModel = new CellSetModel();
394     RowModel rowModel = new RowModel(ROW_1);
395     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
396       Bytes.toBytes(VALUE_1)));
397     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
398       Bytes.toBytes(VALUE_2)));
399     cellSetModel.addRow(rowModel);
400     rowModel = new RowModel(ROW_2);
401     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
402       Bytes.toBytes(VALUE_3)));
403     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
404       Bytes.toBytes(VALUE_4)));
405     cellSetModel.addRow(rowModel);
406     Response response = client.put(path, Constants.MIMETYPE_PROTOBUF,
407       cellSetModel.createProtobufOutput());
408     Thread.yield();
409 
410     // make sure the fake row was not actually created
411     response = client.get(path, Constants.MIMETYPE_PROTOBUF);
412     assertEquals(404, response.getCode());
413 
414     // check that all of the values were created
415     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
416     checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
417     checkValuePB(TABLE, ROW_2, COLUMN_1, VALUE_3);
418     checkValuePB(TABLE, ROW_2, COLUMN_2, VALUE_4);
419 
420     response = deleteRow(TABLE, ROW_1);
421     assertEquals(200, response.getCode());
422     response = deleteRow(TABLE, ROW_2);
423     assertEquals(200, response.getCode());
424   }
425 
426   @Test
427   public void testStartEndRowGetPutXML() throws IOException, JAXBException {
428     String[] rows = { ROW_1, ROW_2, ROW_3 };
429     String[] values = { VALUE_1, VALUE_2, VALUE_3 };
430     Response response = null;
431     for (int i = 0; i < rows.length; i++) {
432       response = putValueXML(TABLE, rows[i], COLUMN_1, values[i]);
433       assertEquals(200, response.getCode());
434       checkValueXML(TABLE, rows[i], COLUMN_1, values[i]);
435     }
436     response = getValueXML(TABLE, rows[0], rows[2], COLUMN_1);
437     assertEquals(200, response.getCode());
438     CellSetModel cellSet = (CellSetModel)
439       xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
440     assertEquals(2, cellSet.getRows().size());
441     for (int i = 0; i < cellSet.getRows().size()-1; i++) {
442       RowModel rowModel = cellSet.getRows().get(i);
443       for (CellModel cell: rowModel.getCells()) {
444         assertEquals(COLUMN_1, Bytes.toString(cell.getColumn()));
445         assertEquals(values[i], Bytes.toString(cell.getValue()));
446       }
447     }
448     for (String row : rows) {
449       response = deleteRow(TABLE, row);
450       assertEquals(200, response.getCode());
451     }
452   }
453 
454   @Test
455   public void testInvalidCheckParam() throws IOException, JAXBException {
456     CellSetModel cellSetModel = new CellSetModel();
457     RowModel rowModel = new RowModel(ROW_1);
458     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
459       Bytes.toBytes(VALUE_1)));
460     cellSetModel.addRow(rowModel);
461     StringWriter writer = new StringWriter();
462     xmlMarshaller.marshal(cellSetModel, writer);
463 
464     final String path = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1 + "?check=blah";
465 
466     Response response = client.put(path, Constants.MIMETYPE_XML,
467       Bytes.toBytes(writer.toString()));
468     assertEquals(400, response.getCode());
469   }
470 
471   @Test
472   public void testInvalidColumnPut() throws IOException, JAXBException {
473     String dummyColumn = "doesnot:exist";
474     CellSetModel cellSetModel = new CellSetModel();
475     RowModel rowModel = new RowModel(ROW_1);
476     rowModel.addCell(new CellModel(Bytes.toBytes(dummyColumn),
477       Bytes.toBytes(VALUE_1)));
478     cellSetModel.addRow(rowModel);
479     StringWriter writer = new StringWriter();
480     xmlMarshaller.marshal(cellSetModel, writer);
481 
482     final String path = "/" + TABLE + "/" + ROW_1 + "/" + dummyColumn;
483 
484     Response response = client.put(path, Constants.MIMETYPE_XML,
485       Bytes.toBytes(writer.toString()));
486     assertEquals(404, response.getCode());
487   }
488 
489   @Test
490   public void testMultiCellGetJson() throws IOException, JAXBException {
491     String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
492 
493     CellSetModel cellSetModel = new CellSetModel();
494     RowModel rowModel = new RowModel(ROW_1);
495     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
496       Bytes.toBytes(VALUE_1)));
497     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
498       Bytes.toBytes(VALUE_2)));
499     cellSetModel.addRow(rowModel);
500     rowModel = new RowModel(ROW_2);
501     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
502       Bytes.toBytes(VALUE_3)));
503     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
504       Bytes.toBytes(VALUE_4)));
505     cellSetModel.addRow(rowModel);
506     String jsonString = jsonMapper.writeValueAsString(cellSetModel);
507 
508     Response response = client.put(path, Constants.MIMETYPE_JSON,
509       Bytes.toBytes(jsonString));
510     Thread.yield();
511 
512     // make sure the fake row was not actually created
513     response = client.get(path, Constants.MIMETYPE_JSON);
514     assertEquals(404, response.getCode());
515 
516     // check that all of the values were created
517     checkValueJSON(TABLE, ROW_1, COLUMN_1, VALUE_1);
518     checkValueJSON(TABLE, ROW_1, COLUMN_2, VALUE_2);
519     checkValueJSON(TABLE, ROW_2, COLUMN_1, VALUE_3);
520     checkValueJSON(TABLE, ROW_2, COLUMN_2, VALUE_4);
521 
522     response = deleteRow(TABLE, ROW_1);
523     assertEquals(200, response.getCode());
524     response = deleteRow(TABLE, ROW_2);
525     assertEquals(200, response.getCode());
526   }
527   
528   @Test
529   public void testMetrics() throws IOException, JAXBException {
530     final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
531     Response response = client.put(path, Constants.MIMETYPE_BINARY,
532         Bytes.toBytes(VALUE_4));
533     assertEquals(200, response.getCode());
534     Thread.yield();
535     response = client.get(path, Constants.MIMETYPE_JSON);
536     assertEquals(200, response.getCode());
537     assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
538     response = deleteRow(TABLE, ROW_4);
539     assertEquals(200, response.getCode());
540 
541     UserProvider userProvider = UserProvider.instantiate(conf);
542     METRICS_ASSERT.assertCounterGt("requests", 2l,
543       RESTServlet.getInstance(conf, userProvider).getMetrics().getSource());
544 
545     METRICS_ASSERT.assertCounterGt("successfulGet", 0l,
546       RESTServlet.getInstance(conf, userProvider).getMetrics().getSource());
547 
548     METRICS_ASSERT.assertCounterGt("successfulPut", 0l,
549       RESTServlet.getInstance(conf, userProvider).getMetrics().getSource());
550 
551     METRICS_ASSERT.assertCounterGt("successfulDelete", 0l,
552       RESTServlet.getInstance(conf, userProvider).getMetrics().getSource());
553   }
554   
555   @Test
556   public void testMultiColumnGetXML() throws Exception {
557     String path = "/" + TABLE + "/fakerow";
558     CellSetModel cellSetModel = new CellSetModel();
559     RowModel rowModel = new RowModel(ROW_1);
560     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1)));
561     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2)));
562     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_3), Bytes.toBytes(VALUE_2)));
563     cellSetModel.addRow(rowModel);
564     StringWriter writer = new StringWriter();
565     xmlMarshaller.marshal(cellSetModel, writer);
566 
567     Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString()));
568     Thread.yield();
569 
570     // make sure the fake row was not actually created
571     response = client.get(path, Constants.MIMETYPE_XML);
572     assertEquals(404, response.getCode());
573 
574     // Try getting all the column values at once.
575     path = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1 + "," + COLUMN_2 + "," + COLUMN_3;
576     response = client.get(path, Constants.MIMETYPE_XML);
577     assertEquals(200, response.getCode());
578     CellSetModel cellSet = (CellSetModel) xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response
579         .getBody()));
580     assertTrue(cellSet.getRows().size() == 1);
581     assertTrue(cellSet.getRows().get(0).getCells().size() == 3);
582     List<CellModel> cells = cellSet.getRows().get(0).getCells();
583 
584     assertTrue(containsCellModel(cells, COLUMN_1, VALUE_1));
585     assertTrue(containsCellModel(cells, COLUMN_2, VALUE_2));
586     assertTrue(containsCellModel(cells, COLUMN_3, VALUE_2));
587     response = deleteRow(TABLE, ROW_1);
588     assertEquals(200, response.getCode());
589   }
590 
591   private boolean containsCellModel(List<CellModel> cells, String column, String value) {
592     boolean contains = false;
593     for (CellModel cell : cells) {
594       if (Bytes.toString(cell.getColumn()).equals(column)
595           && Bytes.toString(cell.getValue()).equals(value)) {
596         contains = true;
597         return contains;
598       }
599     }
600     return contains;
601   }
602 
603   @Test
604   public void testSuffixGlobbingXMLWithNewScanner() throws IOException, JAXBException {
605     String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
606 
607     CellSetModel cellSetModel = new CellSetModel();
608     RowModel rowModel = new RowModel(ROW_1);
609     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
610       Bytes.toBytes(VALUE_1)));
611     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
612       Bytes.toBytes(VALUE_2)));
613     cellSetModel.addRow(rowModel);
614     rowModel = new RowModel(ROW_2);
615     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
616       Bytes.toBytes(VALUE_3)));
617     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
618       Bytes.toBytes(VALUE_4)));
619     cellSetModel.addRow(rowModel);
620     StringWriter writer = new StringWriter();
621     xmlMarshaller.marshal(cellSetModel, writer);
622     Response response = client.put(path, Constants.MIMETYPE_XML,
623       Bytes.toBytes(writer.toString()));
624     Thread.yield();
625 
626     // make sure the fake row was not actually created
627     response = client.get(path, Constants.MIMETYPE_XML);
628     assertEquals(404, response.getCode());
629 
630     // check that all of the values were created
631     StringBuilder query = new StringBuilder();
632     query.append('/');
633     query.append(TABLE);
634     query.append('/');
635     query.append("testrow*");
636     response = client.get(query.toString(), Constants.MIMETYPE_XML);
637     assertEquals(200, response.getCode());
638     assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
639     CellSetModel cellSet = (CellSetModel)
640       xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
641     assertTrue(cellSet.getRows().size() == 2);
642 
643     response = deleteRow(TABLE, ROW_1);
644     assertEquals(200, response.getCode());
645     response = deleteRow(TABLE, ROW_2);
646     assertEquals(200, response.getCode());
647   }
648 
649   @Test
650   public void testSuffixGlobbingXML() throws IOException, JAXBException {
651     String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
652 
653     CellSetModel cellSetModel = new CellSetModel();
654     RowModel rowModel = new RowModel(ROW_1);
655     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
656       Bytes.toBytes(VALUE_1)));
657     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
658       Bytes.toBytes(VALUE_2)));
659     cellSetModel.addRow(rowModel);
660     rowModel = new RowModel(ROW_2);
661     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
662       Bytes.toBytes(VALUE_3)));
663     rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
664       Bytes.toBytes(VALUE_4)));
665     cellSetModel.addRow(rowModel);
666     StringWriter writer = new StringWriter();
667     xmlMarshaller.marshal(cellSetModel, writer);
668     Response response = client.put(path, Constants.MIMETYPE_XML,
669       Bytes.toBytes(writer.toString()));
670     Thread.yield();
671 
672     // make sure the fake row was not actually created
673     response = client.get(path, Constants.MIMETYPE_XML);
674     assertEquals(404, response.getCode());
675 
676     // check that all of the values were created
677     StringBuilder query = new StringBuilder();
678     query.append('/');
679     query.append(TABLE);
680     query.append('/');
681     query.append("testrow*");
682     query.append('/');
683     query.append(COLUMN_1);
684     response = client.get(query.toString(), Constants.MIMETYPE_XML);
685     assertEquals(200, response.getCode());
686     assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
687     CellSetModel cellSet = (CellSetModel)
688       xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
689     List<RowModel> rows = cellSet.getRows();
690     assertTrue(rows.size() == 2);
691     for (RowModel row : rows) {
692       assertTrue(row.getCells().size() == 1);
693       assertEquals(COLUMN_1, Bytes.toString(row.getCells().get(0).getColumn()));
694     }
695     response = deleteRow(TABLE, ROW_1);
696     assertEquals(200, response.getCode());
697     response = deleteRow(TABLE, ROW_2);
698     assertEquals(200, response.getCode());
699   }
700 
701   @Test
702   public void testAppendXML() throws IOException, JAXBException {
703     Response response = getValueXML(TABLE, ROW_1, COLUMN_1);
704     assertEquals(404, response.getCode());
705 
706     //append cell
707     response = appendValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
708     assertEquals(200, response.getCode());
709     checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
710     response = appendValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
711     assertEquals(200, response.getCode());
712     checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2);
713 
714     response = deleteRow(TABLE, ROW_1);
715     assertEquals(200, response.getCode());
716   }
717 
718   @Test
719   public void testAppendPB() throws IOException, JAXBException {
720     Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
721     assertEquals(404, response.getCode());
722 
723     //append cell
724     response = appendValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
725     assertEquals(200, response.getCode());
726     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
727     response = appendValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2);
728     assertEquals(200, response.getCode());
729     checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2);
730 
731     response = deleteRow(TABLE, ROW_1);
732     assertEquals(200, response.getCode());
733   }
734 
735   @Test
736   public void testAppendJSON() throws IOException, JAXBException {
737     Response response = getValueJson(TABLE, ROW_1, COLUMN_1);
738     assertEquals(404, response.getCode());
739 
740     //append cell
741     response = appendValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1);
742     assertEquals(200, response.getCode());
743     putValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1);
744     response = appendValueJson(TABLE, ROW_1, COLUMN_1, VALUE_2);
745     assertEquals(200, response.getCode());
746     putValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2);
747 
748     response = deleteRow(TABLE, ROW_1);
749     assertEquals(200, response.getCode());
750   }
751 
752   @Test
753   public void testIncrementXML() throws IOException, JAXBException {
754     Response response = getValueXML(TABLE, ROW_1, COLUMN_1);
755     assertEquals(404, response.getCode());
756 
757     //append single cell
758     response = incrementValueXML(TABLE, ROW_1, COLUMN_1, VALUE_5);
759     assertEquals(200, response.getCode());
760     checkIncrementValueXML(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5));
761     response = incrementValueXML(TABLE, ROW_1, COLUMN_1, VALUE_6);
762     assertEquals(200, response.getCode());
763     checkIncrementValueXML(TABLE, ROW_1, COLUMN_1,
764         Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6));
765 
766     response = deleteRow(TABLE, ROW_1);
767     assertEquals(200, response.getCode());
768   }
769 
770   @Test
771   public void testIncrementPB() throws IOException, JAXBException {
772     Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
773     assertEquals(404, response.getCode());
774 
775     //append cell
776     response = incrementValuePB(TABLE, ROW_1, COLUMN_1, VALUE_5);
777     assertEquals(200, response.getCode());
778     checkIncrementValuePB(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5));
779     response = incrementValuePB(TABLE, ROW_1, COLUMN_1, VALUE_6);
780     assertEquals(200, response.getCode());
781     checkIncrementValuePB(TABLE, ROW_1, COLUMN_1,
782         Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6));
783 
784     response = deleteRow(TABLE, ROW_1);
785     assertEquals(200, response.getCode());
786   }
787 
788   @Test
789   public void testIncrementJSON() throws IOException, JAXBException {
790     Response response = getValueJson(TABLE, ROW_1, COLUMN_1);
791     assertEquals(404, response.getCode());
792 
793     //append cell
794     response = incrementValueJson(TABLE, ROW_1, COLUMN_1, VALUE_5);
795     assertEquals(200, response.getCode());
796     checkIncrementValueJSON(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5));
797     response = incrementValueJson(TABLE, ROW_1, COLUMN_1, VALUE_6);
798     assertEquals(200, response.getCode());
799     checkIncrementValueJSON(TABLE, ROW_1, COLUMN_1,
800         Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6));
801 
802     response = deleteRow(TABLE, ROW_1);
803     assertEquals(200, response.getCode());
804   }
805 }