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.io.StringWriter; 026import java.net.URLEncoder; 027import java.util.Base64; 028import java.util.HashMap; 029import java.util.List; 030import javax.xml.bind.JAXBException; 031import org.apache.hadoop.hbase.CompatibilityFactory; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HConstants; 034import org.apache.hadoop.hbase.rest.client.Response; 035import org.apache.hadoop.hbase.rest.model.CellModel; 036import org.apache.hadoop.hbase.rest.model.CellSetModel; 037import org.apache.hadoop.hbase.rest.model.RowModel; 038import org.apache.hadoop.hbase.security.UserProvider; 039import org.apache.hadoop.hbase.test.MetricsAssertHelper; 040import org.apache.hadoop.hbase.testclassification.MediumTests; 041import org.apache.hadoop.hbase.testclassification.RestTests; 042import org.apache.hadoop.hbase.util.Bytes; 043import org.apache.http.Header; 044import org.apache.http.message.BasicHeader; 045import org.junit.ClassRule; 046import org.junit.Test; 047import org.junit.experimental.categories.Category; 048 049@Category({ RestTests.class, MediumTests.class }) 050public class TestGetAndPutResource extends RowResourceBase { 051 @ClassRule 052 public static final HBaseClassTestRule CLASS_RULE = 053 HBaseClassTestRule.forClass(TestGetAndPutResource.class); 054 055 private static final MetricsAssertHelper METRICS_ASSERT = 056 CompatibilityFactory.getInstance(MetricsAssertHelper.class); 057 058 @Test 059 public void testForbidden() throws IOException, JAXBException { 060 conf.set("hbase.rest.readonly", "true"); 061 062 Response response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 063 assertEquals(403, response.getCode()); 064 response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 065 assertEquals(403, response.getCode()); 066 response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2); 067 assertEquals(403, response.getCode()); 068 response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2); 069 assertEquals(403, response.getCode()); 070 response = deleteValue(TABLE, ROW_1, COLUMN_1); 071 assertEquals(403, response.getCode()); 072 response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 073 assertEquals(403, response.getCode()); 074 response = deleteRow(TABLE, ROW_1); 075 assertEquals(403, response.getCode()); 076 077 conf.set("hbase.rest.readonly", "false"); 078 079 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 080 assertEquals(200, response.getCode()); 081 response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 082 assertEquals(200, response.getCode()); 083 response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2); 084 assertEquals(200, response.getCode()); 085 response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3); 086 assertEquals(200, response.getCode()); 087 response = deleteValue(TABLE, ROW_1, COLUMN_1); 088 assertEquals(200, response.getCode()); 089 response = deleteRow(TABLE, ROW_1); 090 assertEquals(200, response.getCode()); 091 } 092 093 @Test 094 public void testSingleCellGetPutXML() throws IOException, JAXBException { 095 Response response = getValueXML(TABLE, ROW_1, COLUMN_1); 096 assertEquals(404, response.getCode()); 097 098 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 099 assertEquals(200, response.getCode()); 100 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 101 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2); 102 assertEquals(200, response.getCode()); 103 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2); 104 response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3); 105 assertEquals(200, response.getCode()); 106 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3); 107 response = checkAndDeleteXML(TABLE, ROW_1, COLUMN_1, VALUE_3); 108 assertEquals(200, response.getCode()); 109 110 response = deleteRow(TABLE, ROW_1); 111 assertEquals(200, response.getCode()); 112 } 113 114 @Test 115 public void testSingleCellGetPutPB() throws IOException, JAXBException { 116 Response response = getValuePB(TABLE, ROW_1, COLUMN_1); 117 assertEquals(404, response.getCode()); 118 119 response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 120 assertEquals(200, response.getCode()); 121 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 122 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2); 123 assertEquals(200, response.getCode()); 124 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2); 125 126 response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3); 127 assertEquals(200, response.getCode()); 128 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3); 129 response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3, VALUE_4); 130 assertEquals(200, response.getCode()); 131 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_4); 132 133 response = deleteRow(TABLE, ROW_1); 134 assertEquals(200, response.getCode()); 135 } 136 137 @Test 138 public void testMultipleCellCheckPutPB() throws IOException { 139 Response response = getValuePB(TABLE, ROW_1, COLUMN_1); 140 assertEquals(404, response.getCode()); 141 142 // Add 2 Columns to setup the test 143 response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 144 assertEquals(200, response.getCode()); 145 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 146 147 response = putValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 148 assertEquals(200, response.getCode()); 149 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 150 151 HashMap<String, String> otherCells = new HashMap<>(); 152 otherCells.put(COLUMN_2, VALUE_3); 153 154 // On Success update both the cells 155 response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_3, otherCells); 156 assertEquals(200, response.getCode()); 157 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3); 158 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_3); 159 160 // On Failure, we dont update any cells 161 response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_4, otherCells); 162 assertEquals(304, response.getCode()); 163 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3); 164 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_3); 165 166 response = deleteRow(TABLE, ROW_1); 167 assertEquals(200, response.getCode()); 168 } 169 170 @Test 171 public void testMultipleCellCheckPutXML() throws IOException, JAXBException { 172 Response response = getValuePB(TABLE, ROW_1, COLUMN_1); 173 assertEquals(404, response.getCode()); 174 175 // Add 2 Columns to setup the test 176 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 177 assertEquals(200, response.getCode()); 178 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 179 180 response = putValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2); 181 assertEquals(200, response.getCode()); 182 checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2); 183 184 HashMap<String, String> otherCells = new HashMap<>(); 185 otherCells.put(COLUMN_2, VALUE_3); 186 187 // On Success update both the cells 188 response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_3, otherCells); 189 assertEquals(200, response.getCode()); 190 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3); 191 checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_3); 192 193 // On Failure, we dont update any cells 194 response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_4, otherCells); 195 assertEquals(304, response.getCode()); 196 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3); 197 checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_3); 198 199 response = deleteRow(TABLE, ROW_1); 200 assertEquals(200, response.getCode()); 201 } 202 203 @Test 204 public void testMultipleCellCheckDeletePB() throws IOException { 205 Response response = getValuePB(TABLE, ROW_1, COLUMN_1); 206 assertEquals(404, response.getCode()); 207 208 // Add 3 Columns to setup the test 209 response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 210 assertEquals(200, response.getCode()); 211 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 212 213 response = putValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 214 assertEquals(200, response.getCode()); 215 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 216 217 response = putValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3); 218 assertEquals(200, response.getCode()); 219 checkValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3); 220 221 // Deletes the following columns based on Column1 check 222 HashMap<String, String> cellsToDelete = new HashMap<>(); 223 cellsToDelete.put(COLUMN_2, VALUE_2); // Value does not matter 224 cellsToDelete.put(COLUMN_3, VALUE_3); // Value does not matter 225 226 // On Success update both the cells 227 response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_1, cellsToDelete); 228 assertEquals(200, response.getCode()); 229 230 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 231 232 response = getValuePB(TABLE, ROW_1, COLUMN_2); 233 assertEquals(404, response.getCode()); 234 235 response = getValuePB(TABLE, ROW_1, COLUMN_3); 236 assertEquals(404, response.getCode()); 237 238 response = putValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 239 assertEquals(200, response.getCode()); 240 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 241 242 response = putValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3); 243 assertEquals(200, response.getCode()); 244 checkValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3); 245 246 // On Failure, we dont update any cells 247 response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_3, cellsToDelete); 248 assertEquals(304, response.getCode()); 249 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 250 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 251 checkValuePB(TABLE, ROW_1, COLUMN_3, VALUE_3); 252 253 response = deleteRow(TABLE, ROW_1); 254 assertEquals(200, response.getCode()); 255 } 256 257 @Test 258 public void testSingleCellGetPutBinary() throws IOException { 259 final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1; 260 final byte[] body = Bytes.toBytes(VALUE_3); 261 Response response = client.put(path, Constants.MIMETYPE_BINARY, body); 262 assertEquals(200, response.getCode()); 263 Thread.yield(); 264 265 response = client.get(path, Constants.MIMETYPE_BINARY); 266 assertEquals(200, response.getCode()); 267 assertEquals(Constants.MIMETYPE_BINARY, response.getHeader("content-type")); 268 assertTrue(Bytes.equals(response.getBody(), body)); 269 boolean foundTimestampHeader = false; 270 for (Header header : response.getHeaders()) { 271 if (header.getName().equals("X-Timestamp")) { 272 foundTimestampHeader = true; 273 break; 274 } 275 } 276 assertTrue(foundTimestampHeader); 277 278 response = deleteRow(TABLE, ROW_3); 279 assertEquals(200, response.getCode()); 280 } 281 282 @Test 283 public void testSingleCellGetJSON() throws IOException { 284 final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1; 285 Response response = client.put(path, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_4)); 286 assertEquals(200, response.getCode()); 287 Thread.yield(); 288 response = client.get(path, Constants.MIMETYPE_JSON); 289 assertEquals(200, response.getCode()); 290 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 291 response = deleteRow(TABLE, ROW_4); 292 assertEquals(200, response.getCode()); 293 } 294 295 @Test 296 public void testLatestCellGetJSON() throws IOException { 297 final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1; 298 CellSetModel cellSetModel = new CellSetModel(); 299 RowModel rowModel = new RowModel(ROW_4); 300 CellModel cellOne = new CellModel(Bytes.toBytes(COLUMN_1), 1L, Bytes.toBytes(VALUE_1)); 301 CellModel cellTwo = new CellModel(Bytes.toBytes(COLUMN_1), 2L, Bytes.toBytes(VALUE_2)); 302 rowModel.addCell(cellOne); 303 rowModel.addCell(cellTwo); 304 cellSetModel.addRow(rowModel); 305 String jsonString = jsonMapper.writeValueAsString(cellSetModel); 306 Response response = client.put(path, Constants.MIMETYPE_JSON, Bytes.toBytes(jsonString)); 307 assertEquals(200, response.getCode()); 308 Thread.yield(); 309 response = client.get(path, Constants.MIMETYPE_JSON); 310 assertEquals(200, response.getCode()); 311 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 312 CellSetModel cellSet = jsonMapper.readValue(response.getBody(), CellSetModel.class); 313 assertTrue(cellSet.getRows().size() == 1); 314 assertTrue(cellSet.getRows().get(0).getCells().size() == 1); 315 CellModel cell = cellSet.getRows().get(0).getCells().get(0); 316 assertEquals(VALUE_2, Bytes.toString(cell.getValue())); 317 assertEquals(2L, cell.getTimestamp()); 318 response = deleteRow(TABLE, ROW_4); 319 assertEquals(200, response.getCode()); 320 } 321 322 @Test 323 public void testURLEncodedKey() throws IOException, JAXBException { 324 String urlKey = "http://example.com/foo"; 325 StringBuilder path = new StringBuilder(); 326 path.append('/'); 327 path.append(TABLE); 328 path.append('/'); 329 path.append(URLEncoder.encode(urlKey, HConstants.UTF8_ENCODING)); 330 path.append('/'); 331 path.append(COLUMN_1); 332 Response response; 333 response = putValueXML(path.toString(), TABLE, urlKey, COLUMN_1, VALUE_1); 334 assertEquals(200, response.getCode()); 335 checkValueXML(path.toString(), TABLE, urlKey, COLUMN_1, VALUE_1); 336 } 337 338 private void setupValue1() throws IOException, JAXBException { 339 StringBuilder path = new StringBuilder(); 340 path.append('/'); 341 path.append(TABLE); 342 path.append('/'); 343 path.append(ROW_1); 344 path.append('/'); 345 path.append(COLUMN_1); 346 Response response = putValueXML(path.toString(), TABLE, ROW_1, COLUMN_1, VALUE_1); 347 assertEquals(200, response.getCode()); 348 } 349 350 private void checkValue1(Response getResponse) throws JAXBException { 351 assertEquals(Constants.MIMETYPE_XML, getResponse.getHeader("content-type")); 352 353 CellSetModel cellSet = 354 (CellSetModel) xmlUnmarshaller.unmarshal(new ByteArrayInputStream(getResponse.getBody())); 355 assertEquals(1, cellSet.getRows().size()); 356 RowModel rowModel = cellSet.getRows().get(0); 357 assertEquals(ROW_1, new String(rowModel.getKey())); 358 assertEquals(1, rowModel.getCells().size()); 359 CellModel cell = rowModel.getCells().get(0); 360 assertEquals(COLUMN_1, new String(cell.getColumn())); 361 assertEquals(VALUE_1, new String(cell.getValue())); 362 } 363 364 // See https://issues.apache.org/jira/browse/HBASE-28174 365 @Test 366 public void testUrlB64EncodedKeyQueryParam() throws IOException, JAXBException { 367 setupValue1(); 368 369 StringBuilder path = new StringBuilder(); 370 Base64.Encoder encoder = Base64.getUrlEncoder(); 371 path.append('/'); 372 path.append(TABLE); 373 path.append('/'); 374 path.append(encoder.encodeToString(ROW_1.getBytes("UTF-8"))); 375 path.append('/'); 376 path.append(encoder.encodeToString(COLUMN_1.getBytes("UTF-8"))); 377 path.append("?e=b64"); 378 Response response = getValueXML(path.toString()); 379 assertEquals(200, response.getCode()); 380 381 checkValue1(response); 382 } 383 384 // See https://issues.apache.org/jira/browse/HBASE-28174 385 @Test 386 public void testUrlB64EncodedKeyHeader() throws IOException, JAXBException { 387 setupValue1(); 388 389 StringBuilder path = new StringBuilder(); 390 Base64.Encoder encoder = Base64.getUrlEncoder(); 391 path.append('/'); 392 path.append(TABLE); 393 path.append('/'); 394 path.append(encoder.encodeToString(ROW_1.getBytes("UTF-8"))); 395 path.append('/'); 396 path.append(encoder.encodeToString(COLUMN_1.getBytes("UTF-8"))); 397 Response response = 398 getValueXML(path.toString(), new Header[] { new BasicHeader("Encoding", "b64") }); 399 assertEquals(200, response.getCode()); 400 401 checkValue1(response); 402 } 403 404 @Test 405 public void testNoSuchCF() throws IOException { 406 final String goodPath = "/" + TABLE + "/" + ROW_1 + "/" + CFA + ":"; 407 final String badPath = "/" + TABLE + "/" + ROW_1 + "/" + "BAD"; 408 Response response = client.post(goodPath, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1)); 409 assertEquals(200, response.getCode()); 410 assertEquals(200, client.get(goodPath, Constants.MIMETYPE_BINARY).getCode()); 411 assertEquals(404, client.get(badPath, Constants.MIMETYPE_BINARY).getCode()); 412 assertEquals(200, client.get(goodPath, Constants.MIMETYPE_BINARY).getCode()); 413 } 414 415 @Test 416 public void testMultiCellGetPutXML() throws IOException, JAXBException { 417 String path = "/" + TABLE + "/fakerow"; // deliberate nonexistent row 418 419 CellSetModel cellSetModel = new CellSetModel(); 420 RowModel rowModel = new RowModel(ROW_1); 421 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); 422 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2))); 423 cellSetModel.addRow(rowModel); 424 rowModel = new RowModel(ROW_2); 425 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_3))); 426 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_4))); 427 cellSetModel.addRow(rowModel); 428 StringWriter writer = new StringWriter(); 429 xmlMarshaller.marshal(cellSetModel, writer); 430 Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString())); 431 Thread.yield(); 432 433 // make sure the fake row was not actually created 434 response = client.get(path, Constants.MIMETYPE_XML); 435 assertEquals(404, response.getCode()); 436 437 // check that all of the values were created 438 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 439 checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2); 440 checkValueXML(TABLE, ROW_2, COLUMN_1, VALUE_3); 441 checkValueXML(TABLE, ROW_2, COLUMN_2, VALUE_4); 442 443 response = deleteRow(TABLE, ROW_1); 444 assertEquals(200, response.getCode()); 445 response = deleteRow(TABLE, ROW_2); 446 assertEquals(200, response.getCode()); 447 } 448 449 @Test 450 public void testMultiCellGetPutPB() throws IOException { 451 String path = "/" + TABLE + "/fakerow"; // deliberate nonexistent row 452 453 CellSetModel cellSetModel = new CellSetModel(); 454 RowModel rowModel = new RowModel(ROW_1); 455 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); 456 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2))); 457 cellSetModel.addRow(rowModel); 458 rowModel = new RowModel(ROW_2); 459 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_3))); 460 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_4))); 461 cellSetModel.addRow(rowModel); 462 Response response = 463 client.put(path, Constants.MIMETYPE_PROTOBUF, cellSetModel.createProtobufOutput()); 464 Thread.yield(); 465 466 // make sure the fake row was not actually created 467 response = client.get(path, Constants.MIMETYPE_PROTOBUF); 468 assertEquals(404, response.getCode()); 469 470 // check that all of the values were created 471 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 472 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); 473 checkValuePB(TABLE, ROW_2, COLUMN_1, VALUE_3); 474 checkValuePB(TABLE, ROW_2, COLUMN_2, VALUE_4); 475 476 response = deleteRow(TABLE, ROW_1); 477 assertEquals(200, response.getCode()); 478 response = deleteRow(TABLE, ROW_2); 479 assertEquals(200, response.getCode()); 480 } 481 482 @Test 483 public void testStartEndRowGetPutXML() throws IOException, JAXBException { 484 String[] rows = { ROW_1, ROW_2, ROW_3 }; 485 String[] values = { VALUE_1, VALUE_2, VALUE_3 }; 486 Response response = null; 487 for (int i = 0; i < rows.length; i++) { 488 response = putValueXML(TABLE, rows[i], COLUMN_1, values[i]); 489 assertEquals(200, response.getCode()); 490 checkValueXML(TABLE, rows[i], COLUMN_1, values[i]); 491 } 492 response = getValueXML(TABLE, rows[0], rows[2], COLUMN_1); 493 assertEquals(200, response.getCode()); 494 CellSetModel cellSet = 495 (CellSetModel) xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody())); 496 assertEquals(2, cellSet.getRows().size()); 497 for (int i = 0; i < cellSet.getRows().size() - 1; i++) { 498 RowModel rowModel = cellSet.getRows().get(i); 499 for (CellModel cell : rowModel.getCells()) { 500 assertEquals(COLUMN_1, Bytes.toString(cell.getColumn())); 501 assertEquals(values[i], Bytes.toString(cell.getValue())); 502 } 503 } 504 for (String row : rows) { 505 response = deleteRow(TABLE, row); 506 assertEquals(200, response.getCode()); 507 } 508 } 509 510 @Test 511 public void testInvalidCheckParam() throws IOException, JAXBException { 512 CellSetModel cellSetModel = new CellSetModel(); 513 RowModel rowModel = new RowModel(ROW_1); 514 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); 515 cellSetModel.addRow(rowModel); 516 StringWriter writer = new StringWriter(); 517 xmlMarshaller.marshal(cellSetModel, writer); 518 519 final String path = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1 + "?check=blah"; 520 521 Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString())); 522 assertEquals(400, response.getCode()); 523 } 524 525 @Test 526 public void testInvalidColumnPut() throws IOException, JAXBException { 527 String dummyColumn = "doesnot:exist"; 528 CellSetModel cellSetModel = new CellSetModel(); 529 RowModel rowModel = new RowModel(ROW_1); 530 rowModel.addCell(new CellModel(Bytes.toBytes(dummyColumn), Bytes.toBytes(VALUE_1))); 531 cellSetModel.addRow(rowModel); 532 StringWriter writer = new StringWriter(); 533 xmlMarshaller.marshal(cellSetModel, writer); 534 535 final String path = "/" + TABLE + "/" + ROW_1 + "/" + dummyColumn; 536 537 Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString())); 538 assertEquals(404, response.getCode()); 539 } 540 541 @Test 542 public void testMultiCellGetJson() throws IOException, JAXBException { 543 String path = "/" + TABLE + "/fakerow"; // deliberate nonexistent row 544 545 CellSetModel cellSetModel = new CellSetModel(); 546 RowModel rowModel = new RowModel(ROW_1); 547 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); 548 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2))); 549 cellSetModel.addRow(rowModel); 550 rowModel = new RowModel(ROW_2); 551 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_3))); 552 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_4))); 553 cellSetModel.addRow(rowModel); 554 String jsonString = jsonMapper.writeValueAsString(cellSetModel); 555 556 Response response = client.put(path, Constants.MIMETYPE_JSON, Bytes.toBytes(jsonString)); 557 Thread.yield(); 558 559 // make sure the fake row was not actually created 560 response = client.get(path, Constants.MIMETYPE_JSON); 561 assertEquals(404, response.getCode()); 562 563 // check that all of the values were created 564 checkValueJSON(TABLE, ROW_1, COLUMN_1, VALUE_1); 565 checkValueJSON(TABLE, ROW_1, COLUMN_2, VALUE_2); 566 checkValueJSON(TABLE, ROW_2, COLUMN_1, VALUE_3); 567 checkValueJSON(TABLE, ROW_2, COLUMN_2, VALUE_4); 568 569 response = deleteRow(TABLE, ROW_1); 570 assertEquals(200, response.getCode()); 571 response = deleteRow(TABLE, ROW_2); 572 assertEquals(200, response.getCode()); 573 } 574 575 @Test 576 public void testMetrics() throws IOException { 577 final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1; 578 Response response = client.put(path, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_4)); 579 assertEquals(200, response.getCode()); 580 Thread.yield(); 581 response = client.get(path, Constants.MIMETYPE_JSON); 582 assertEquals(200, response.getCode()); 583 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 584 response = deleteRow(TABLE, ROW_4); 585 assertEquals(200, response.getCode()); 586 587 UserProvider userProvider = UserProvider.instantiate(conf); 588 METRICS_ASSERT.assertCounterGt("requests", 2L, 589 RESTServlet.getInstance(conf, userProvider).getMetrics().getSource()); 590 591 METRICS_ASSERT.assertCounterGt("successfulGet", 0L, 592 RESTServlet.getInstance(conf, userProvider).getMetrics().getSource()); 593 594 METRICS_ASSERT.assertCounterGt("successfulPut", 0L, 595 RESTServlet.getInstance(conf, userProvider).getMetrics().getSource()); 596 597 METRICS_ASSERT.assertCounterGt("successfulDelete", 0L, 598 RESTServlet.getInstance(conf, userProvider).getMetrics().getSource()); 599 } 600 601 @Test 602 public void testMultiColumnGetXML() throws Exception { 603 String path = "/" + TABLE + "/fakerow"; 604 CellSetModel cellSetModel = new CellSetModel(); 605 RowModel rowModel = new RowModel(ROW_1); 606 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); 607 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2))); 608 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_3), Bytes.toBytes(VALUE_2))); 609 cellSetModel.addRow(rowModel); 610 StringWriter writer = new StringWriter(); 611 xmlMarshaller.marshal(cellSetModel, writer); 612 613 Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString())); 614 Thread.yield(); 615 616 // make sure the fake row was not actually created 617 response = client.get(path, Constants.MIMETYPE_XML); 618 assertEquals(404, response.getCode()); 619 620 // Try getting all the column values at once. 621 path = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1 + "," + COLUMN_2 + "," + COLUMN_3; 622 response = client.get(path, Constants.MIMETYPE_XML); 623 assertEquals(200, response.getCode()); 624 CellSetModel cellSet = 625 (CellSetModel) xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody())); 626 assertTrue(cellSet.getRows().size() == 1); 627 assertTrue(cellSet.getRows().get(0).getCells().size() == 3); 628 List<CellModel> cells = cellSet.getRows().get(0).getCells(); 629 630 assertTrue(containsCellModel(cells, COLUMN_1, VALUE_1)); 631 assertTrue(containsCellModel(cells, COLUMN_2, VALUE_2)); 632 assertTrue(containsCellModel(cells, COLUMN_3, VALUE_2)); 633 response = deleteRow(TABLE, ROW_1); 634 assertEquals(200, response.getCode()); 635 } 636 637 private boolean containsCellModel(List<CellModel> cells, String column, String value) { 638 boolean contains = false; 639 for (CellModel cell : cells) { 640 if ( 641 Bytes.toString(cell.getColumn()).equals(column) 642 && Bytes.toString(cell.getValue()).equals(value) 643 ) { 644 contains = true; 645 return contains; 646 } 647 } 648 return contains; 649 } 650 651 @Test 652 public void testSuffixGlobbingXMLWithNewScanner() throws IOException, JAXBException { 653 String path = "/" + TABLE + "/fakerow"; // deliberate nonexistent row 654 655 CellSetModel cellSetModel = new CellSetModel(); 656 RowModel rowModel = new RowModel(ROW_1); 657 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); 658 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2))); 659 cellSetModel.addRow(rowModel); 660 rowModel = new RowModel(ROW_2); 661 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_3))); 662 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_4))); 663 cellSetModel.addRow(rowModel); 664 StringWriter writer = new StringWriter(); 665 xmlMarshaller.marshal(cellSetModel, writer); 666 Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString())); 667 Thread.yield(); 668 669 // make sure the fake row was not actually created 670 response = client.get(path, Constants.MIMETYPE_XML); 671 assertEquals(404, response.getCode()); 672 673 // check that all of the values were created 674 StringBuilder query = new StringBuilder(); 675 query.append('/'); 676 query.append(TABLE); 677 query.append('/'); 678 query.append("testrow*"); 679 response = client.get(query.toString(), Constants.MIMETYPE_XML); 680 assertEquals(200, response.getCode()); 681 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 682 CellSetModel cellSet = 683 (CellSetModel) xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody())); 684 assertTrue(cellSet.getRows().size() == 2); 685 686 response = deleteRow(TABLE, ROW_1); 687 assertEquals(200, response.getCode()); 688 response = deleteRow(TABLE, ROW_2); 689 assertEquals(200, response.getCode()); 690 } 691 692 @Test 693 public void testSuffixGlobbingXML() throws IOException, JAXBException { 694 String path = "/" + TABLE + "/fakerow"; // deliberate nonexistent row 695 696 CellSetModel cellSetModel = new CellSetModel(); 697 RowModel rowModel = new RowModel(ROW_1); 698 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); 699 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2))); 700 cellSetModel.addRow(rowModel); 701 rowModel = new RowModel(ROW_2); 702 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_3))); 703 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_4))); 704 cellSetModel.addRow(rowModel); 705 StringWriter writer = new StringWriter(); 706 xmlMarshaller.marshal(cellSetModel, writer); 707 Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString())); 708 Thread.yield(); 709 710 // make sure the fake row was not actually created 711 response = client.get(path, Constants.MIMETYPE_XML); 712 assertEquals(404, response.getCode()); 713 714 // check that all of the values were created 715 StringBuilder query = new StringBuilder(); 716 query.append('/'); 717 query.append(TABLE); 718 query.append('/'); 719 query.append("testrow*"); 720 query.append('/'); 721 query.append(COLUMN_1); 722 response = client.get(query.toString(), Constants.MIMETYPE_XML); 723 assertEquals(200, response.getCode()); 724 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 725 CellSetModel cellSet = 726 (CellSetModel) xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody())); 727 List<RowModel> rows = cellSet.getRows(); 728 assertTrue(rows.size() == 2); 729 for (RowModel row : rows) { 730 assertTrue(row.getCells().size() == 1); 731 assertEquals(COLUMN_1, Bytes.toString(row.getCells().get(0).getColumn())); 732 } 733 response = deleteRow(TABLE, ROW_1); 734 assertEquals(200, response.getCode()); 735 response = deleteRow(TABLE, ROW_2); 736 assertEquals(200, response.getCode()); 737 } 738 739 @Test 740 public void testAppendXML() throws IOException, JAXBException { 741 Response response = getValueXML(TABLE, ROW_1, COLUMN_1); 742 assertEquals(404, response.getCode()); 743 744 // append cell 745 response = appendValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 746 assertEquals(200, response.getCode()); 747 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); 748 response = appendValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2); 749 assertEquals(200, response.getCode()); 750 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2); 751 752 response = deleteRow(TABLE, ROW_1); 753 assertEquals(200, response.getCode()); 754 } 755 756 @Test 757 public void testAppendPB() throws IOException, JAXBException { 758 Response response = getValuePB(TABLE, ROW_1, COLUMN_1); 759 assertEquals(404, response.getCode()); 760 761 // append cell 762 response = appendValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 763 assertEquals(200, response.getCode()); 764 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); 765 response = appendValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2); 766 assertEquals(200, response.getCode()); 767 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2); 768 769 response = deleteRow(TABLE, ROW_1); 770 assertEquals(200, response.getCode()); 771 } 772 773 @Test 774 public void testAppendJSON() throws IOException, JAXBException { 775 Response response = getValueJson(TABLE, ROW_1, COLUMN_1); 776 assertEquals(404, response.getCode()); 777 778 // append cell 779 response = appendValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1); 780 assertEquals(200, response.getCode()); 781 putValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1); 782 response = appendValueJson(TABLE, ROW_1, COLUMN_1, VALUE_2); 783 assertEquals(200, response.getCode()); 784 putValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2); 785 786 response = deleteRow(TABLE, ROW_1); 787 assertEquals(200, response.getCode()); 788 } 789 790 @Test 791 public void testIncrementXML() throws IOException, JAXBException { 792 Response response = getValueXML(TABLE, ROW_1, COLUMN_1); 793 assertEquals(404, response.getCode()); 794 795 // append single cell 796 response = incrementValueXML(TABLE, ROW_1, COLUMN_1, VALUE_5); 797 assertEquals(200, response.getCode()); 798 checkIncrementValueXML(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5)); 799 response = incrementValueXML(TABLE, ROW_1, COLUMN_1, VALUE_6); 800 assertEquals(200, response.getCode()); 801 checkIncrementValueXML(TABLE, ROW_1, COLUMN_1, 802 Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6)); 803 804 response = deleteRow(TABLE, ROW_1); 805 assertEquals(200, response.getCode()); 806 } 807 808 @Test 809 public void testIncrementPB() throws IOException, JAXBException { 810 Response response = getValuePB(TABLE, ROW_1, COLUMN_1); 811 assertEquals(404, response.getCode()); 812 813 // append cell 814 response = incrementValuePB(TABLE, ROW_1, COLUMN_1, VALUE_5); 815 assertEquals(200, response.getCode()); 816 checkIncrementValuePB(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5)); 817 response = incrementValuePB(TABLE, ROW_1, COLUMN_1, VALUE_6); 818 assertEquals(200, response.getCode()); 819 checkIncrementValuePB(TABLE, ROW_1, COLUMN_1, 820 Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6)); 821 822 response = deleteRow(TABLE, ROW_1); 823 assertEquals(200, response.getCode()); 824 } 825 826 @Test 827 public void testIncrementJSON() throws IOException, JAXBException { 828 Response response = getValueJson(TABLE, ROW_1, COLUMN_1); 829 assertEquals(404, response.getCode()); 830 831 // append cell 832 response = incrementValueJson(TABLE, ROW_1, COLUMN_1, VALUE_5); 833 assertEquals(200, response.getCode()); 834 checkIncrementValueJSON(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5)); 835 response = incrementValueJson(TABLE, ROW_1, COLUMN_1, VALUE_6); 836 assertEquals(200, response.getCode()); 837 checkIncrementValueJSON(TABLE, ROW_1, COLUMN_1, 838 Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6)); 839 840 response = deleteRow(TABLE, ROW_1); 841 assertEquals(200, response.getCode()); 842 } 843}