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.client; 019 020import static org.junit.jupiter.api.Assertions.assertArrayEquals; 021import static org.junit.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertNotNull; 023 024import java.io.IOException; 025import java.lang.reflect.Type; 026import java.nio.ByteBuffer; 027import java.util.Arrays; 028import java.util.List; 029import java.util.Map; 030import org.apache.hadoop.hbase.Cell; 031import org.apache.hadoop.hbase.CellComparatorImpl; 032import org.apache.hadoop.hbase.CellUtil; 033import org.apache.hadoop.hbase.CompareOperator; 034import org.apache.hadoop.hbase.ExtendedCell; 035import org.apache.hadoop.hbase.HConstants; 036import org.apache.hadoop.hbase.KeyValue; 037import org.apache.hadoop.hbase.filter.BinaryComparator; 038import org.apache.hadoop.hbase.filter.ColumnCountGetFilter; 039import org.apache.hadoop.hbase.filter.ColumnPaginationFilter; 040import org.apache.hadoop.hbase.filter.ColumnPrefixFilter; 041import org.apache.hadoop.hbase.filter.ColumnRangeFilter; 042import org.apache.hadoop.hbase.filter.DependentColumnFilter; 043import org.apache.hadoop.hbase.filter.FamilyFilter; 044import org.apache.hadoop.hbase.filter.Filter; 045import org.apache.hadoop.hbase.filter.FilterList; 046import org.apache.hadoop.hbase.filter.FilterList.Operator; 047import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter; 048import org.apache.hadoop.hbase.filter.InclusiveStopFilter; 049import org.apache.hadoop.hbase.filter.KeyOnlyFilter; 050import org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter; 051import org.apache.hadoop.hbase.filter.PageFilter; 052import org.apache.hadoop.hbase.filter.PrefixFilter; 053import org.apache.hadoop.hbase.filter.QualifierFilter; 054import org.apache.hadoop.hbase.filter.RowFilter; 055import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter; 056import org.apache.hadoop.hbase.filter.SingleColumnValueFilter; 057import org.apache.hadoop.hbase.filter.SkipFilter; 058import org.apache.hadoop.hbase.filter.TimestampsFilter; 059import org.apache.hadoop.hbase.filter.ValueFilter; 060import org.apache.hadoop.hbase.filter.WhileMatchFilter; 061import org.apache.hadoop.hbase.testclassification.ClientTests; 062import org.apache.hadoop.hbase.testclassification.SmallTests; 063import org.apache.hadoop.hbase.util.BuilderStyleTest; 064import org.apache.hadoop.hbase.util.Bytes; 065import org.apache.hadoop.hbase.util.GsonUtil; 066import org.junit.jupiter.api.Tag; 067import org.junit.jupiter.api.Test; 068 069import org.apache.hbase.thirdparty.com.google.common.reflect.TypeToken; 070import org.apache.hbase.thirdparty.com.google.gson.Gson; 071import org.apache.hbase.thirdparty.com.google.gson.GsonBuilder; 072import org.apache.hbase.thirdparty.com.google.gson.LongSerializationPolicy; 073import org.apache.hbase.thirdparty.com.google.gson.ToNumberPolicy; 074 075/** 076 * Run tests that use the functionality of the Operation superclass for Puts, Gets, Deletes, Scans, 077 * and MultiPuts. 078 */ 079@Tag(ClientTests.TAG) 080@Tag(SmallTests.TAG) 081public class TestOperation { 082 083 private static byte[] ROW = Bytes.toBytes("testRow"); 084 private static byte[] FAMILY = Bytes.toBytes("testFamily"); 085 private static byte[] QUALIFIER = Bytes.toBytes("testQualifier"); 086 private static byte[] VALUE = Bytes.toBytes("testValue"); 087 088 private static Gson GSON = GsonUtil.createGson().create(); 089 090 private static List<Long> TS_LIST = Arrays.asList(2L, 3L, 5L); 091 private static TimestampsFilter TS_FILTER = new TimestampsFilter(TS_LIST); 092 private static String STR_TS_FILTER = TS_FILTER.getClass().getSimpleName() + " (3/3): [2, 3, 5]"; 093 094 private static List<Long> L_TS_LIST = Arrays.asList(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L); 095 private static TimestampsFilter L_TS_FILTER = new TimestampsFilter(L_TS_LIST); 096 private static String STR_L_TS_FILTER = 097 L_TS_FILTER.getClass().getSimpleName() + " (5/11): [0, 1, 2, 3, 4]"; 098 099 private static String COL_NAME_1 = "col1"; 100 private static ColumnPrefixFilter COL_PRE_FILTER = 101 new ColumnPrefixFilter(Bytes.toBytes(COL_NAME_1)); 102 private static String STR_COL_PRE_FILTER = 103 COL_PRE_FILTER.getClass().getSimpleName() + " " + COL_NAME_1; 104 105 private static String COL_NAME_2 = "col2"; 106 private static ColumnRangeFilter CR_FILTER = 107 new ColumnRangeFilter(Bytes.toBytes(COL_NAME_1), true, Bytes.toBytes(COL_NAME_2), false); 108 private static String STR_CR_FILTER = 109 CR_FILTER.getClass().getSimpleName() + " [" + COL_NAME_1 + ", " + COL_NAME_2 + ")"; 110 111 private static int COL_COUNT = 9; 112 private static ColumnCountGetFilter CCG_FILTER = new ColumnCountGetFilter(COL_COUNT); 113 private static String STR_CCG_FILTER = CCG_FILTER.getClass().getSimpleName() + " " + COL_COUNT; 114 115 private static int LIMIT = 3; 116 private static int OFFSET = 4; 117 private static ColumnPaginationFilter CP_FILTER = new ColumnPaginationFilter(LIMIT, OFFSET); 118 private static String STR_CP_FILTER = 119 CP_FILTER.getClass().getSimpleName() + " (" + LIMIT + ", " + OFFSET + ")"; 120 121 private static String STOP_ROW_KEY = "stop"; 122 private static InclusiveStopFilter IS_FILTER = 123 new InclusiveStopFilter(Bytes.toBytes(STOP_ROW_KEY)); 124 private static String STR_IS_FILTER = IS_FILTER.getClass().getSimpleName() + " " + STOP_ROW_KEY; 125 126 private static String PREFIX = "prefix"; 127 private static PrefixFilter PREFIX_FILTER = new PrefixFilter(Bytes.toBytes(PREFIX)); 128 private static String STR_PREFIX_FILTER = "PrefixFilter " + PREFIX; 129 130 private static byte[][] PREFIXES = { Bytes.toBytes("0"), Bytes.toBytes("1"), Bytes.toBytes("2") }; 131 private static MultipleColumnPrefixFilter MCP_FILTER = new MultipleColumnPrefixFilter(PREFIXES); 132 private static String STR_MCP_FILTER = 133 MCP_FILTER.getClass().getSimpleName() + " (3/3): [0, 1, 2]"; 134 135 private static byte[][] L_PREFIXES = 136 { Bytes.toBytes("0"), Bytes.toBytes("1"), Bytes.toBytes("2"), Bytes.toBytes("3"), 137 Bytes.toBytes("4"), Bytes.toBytes("5"), Bytes.toBytes("6"), Bytes.toBytes("7") }; 138 private static MultipleColumnPrefixFilter L_MCP_FILTER = 139 new MultipleColumnPrefixFilter(L_PREFIXES); 140 private static String STR_L_MCP_FILTER = 141 L_MCP_FILTER.getClass().getSimpleName() + " (5/8): [0, 1, 2, 3, 4]"; 142 143 private static int PAGE_SIZE = 9; 144 private static PageFilter PAGE_FILTER = new PageFilter(PAGE_SIZE); 145 private static String STR_PAGE_FILTER = PAGE_FILTER.getClass().getSimpleName() + " " + PAGE_SIZE; 146 147 private static SkipFilter SKIP_FILTER = new SkipFilter(L_TS_FILTER); 148 private static String STR_SKIP_FILTER = 149 SKIP_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER; 150 151 private static WhileMatchFilter WHILE_FILTER = new WhileMatchFilter(L_TS_FILTER); 152 private static String STR_WHILE_FILTER = 153 WHILE_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER; 154 155 private static KeyOnlyFilter KEY_ONLY_FILTER = new KeyOnlyFilter(); 156 private static String STR_KEY_ONLY_FILTER = KEY_ONLY_FILTER.getClass().getSimpleName(); 157 158 private static FirstKeyOnlyFilter FIRST_KEY_ONLY_FILTER = new FirstKeyOnlyFilter(); 159 private static String STR_FIRST_KEY_ONLY_FILTER = 160 FIRST_KEY_ONLY_FILTER.getClass().getSimpleName(); 161 162 private static CompareOperator CMP_OP = CompareOperator.EQUAL; 163 private static byte[] CMP_VALUE = Bytes.toBytes("value"); 164 private static BinaryComparator BC = new BinaryComparator(CMP_VALUE); 165 private static DependentColumnFilter DC_FILTER = 166 new DependentColumnFilter(FAMILY, QUALIFIER, true, CMP_OP, BC); 167 private static String STR_DC_FILTER = String.format("%s (%s, %s, %s, %s, %s)", 168 DC_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY), 169 Bytes.toStringBinary(QUALIFIER), true, CMP_OP.name(), Bytes.toStringBinary(BC.getValue())); 170 171 private static FamilyFilter FAMILY_FILTER = new FamilyFilter(CMP_OP, BC); 172 private static String STR_FAMILY_FILTER = 173 FAMILY_FILTER.getClass().getSimpleName() + " (EQUAL, value)"; 174 175 private static QualifierFilter QUALIFIER_FILTER = new QualifierFilter(CMP_OP, BC); 176 private static String STR_QUALIFIER_FILTER = 177 QUALIFIER_FILTER.getClass().getSimpleName() + " (EQUAL, value)"; 178 179 private static RowFilter ROW_FILTER = new RowFilter(CMP_OP, BC); 180 private static String STR_ROW_FILTER = ROW_FILTER.getClass().getSimpleName() + " (EQUAL, value)"; 181 182 private static ValueFilter VALUE_FILTER = new ValueFilter(CMP_OP, BC); 183 private static String STR_VALUE_FILTER = 184 VALUE_FILTER.getClass().getSimpleName() + " (EQUAL, value)"; 185 186 private static SingleColumnValueFilter SCV_FILTER = 187 new SingleColumnValueFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE); 188 private static String STR_SCV_FILTER = String.format("%s (%s, %s, %s, %s)", 189 SCV_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY), 190 Bytes.toStringBinary(QUALIFIER), CMP_OP.name(), Bytes.toStringBinary(CMP_VALUE)); 191 192 private static SingleColumnValueExcludeFilter SCVE_FILTER = 193 new SingleColumnValueExcludeFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE); 194 private static String STR_SCVE_FILTER = String.format("%s (%s, %s, %s, %s)", 195 SCVE_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY), 196 Bytes.toStringBinary(QUALIFIER), CMP_OP.name(), Bytes.toStringBinary(CMP_VALUE)); 197 198 private static FilterList AND_FILTER_LIST = new FilterList(Operator.MUST_PASS_ALL, 199 Arrays.asList((Filter) TS_FILTER, L_TS_FILTER, CR_FILTER)); 200 private static String STR_AND_FILTER_LIST = String.format("%s AND (3/3): [%s, %s, %s]", 201 AND_FILTER_LIST.getClass().getSimpleName(), STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER); 202 203 private static FilterList OR_FILTER_LIST = new FilterList(Operator.MUST_PASS_ONE, 204 Arrays.asList((Filter) TS_FILTER, L_TS_FILTER, CR_FILTER)); 205 private static String STR_OR_FILTER_LIST = String.format("%s OR (3/3): [%s, %s, %s]", 206 AND_FILTER_LIST.getClass().getSimpleName(), STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER); 207 208 private static FilterList L_FILTER_LIST = new FilterList(Arrays.asList((Filter) TS_FILTER, 209 L_TS_FILTER, CR_FILTER, COL_PRE_FILTER, CCG_FILTER, CP_FILTER, PREFIX_FILTER, PAGE_FILTER)); 210 private static String STR_L_FILTER_LIST = String.format("%s AND (5/8): [%s, %s, %s, %s, %s, %s]", 211 L_FILTER_LIST.getClass().getSimpleName(), STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER, 212 STR_COL_PRE_FILTER, STR_CCG_FILTER, STR_CP_FILTER); 213 214 private static Filter[] FILTERS = { TS_FILTER, // TimestampsFilter 215 L_TS_FILTER, // TimestampsFilter 216 COL_PRE_FILTER, // ColumnPrefixFilter 217 CP_FILTER, // ColumnPaginationFilter 218 CR_FILTER, // ColumnRangeFilter 219 CCG_FILTER, // ColumnCountGetFilter 220 IS_FILTER, // InclusiveStopFilter 221 PREFIX_FILTER, // PrefixFilter 222 PAGE_FILTER, // PageFilter 223 SKIP_FILTER, // SkipFilter 224 WHILE_FILTER, // WhileMatchFilter 225 KEY_ONLY_FILTER, // KeyOnlyFilter 226 FIRST_KEY_ONLY_FILTER, // FirstKeyOnlyFilter 227 MCP_FILTER, // MultipleColumnPrefixFilter 228 L_MCP_FILTER, // MultipleColumnPrefixFilter 229 DC_FILTER, // DependentColumnFilter 230 FAMILY_FILTER, // FamilyFilter 231 QUALIFIER_FILTER, // QualifierFilter 232 ROW_FILTER, // RowFilter 233 VALUE_FILTER, // ValueFilter 234 SCV_FILTER, // SingleColumnValueFilter 235 SCVE_FILTER, // SingleColumnValueExcludeFilter 236 AND_FILTER_LIST, // FilterList 237 OR_FILTER_LIST, // FilterList 238 L_FILTER_LIST, // FilterList 239 }; 240 241 private static String[] FILTERS_INFO = { STR_TS_FILTER, // TimestampsFilter 242 STR_L_TS_FILTER, // TimestampsFilter 243 STR_COL_PRE_FILTER, // ColumnPrefixFilter 244 STR_CP_FILTER, // ColumnPaginationFilter 245 STR_CR_FILTER, // ColumnRangeFilter 246 STR_CCG_FILTER, // ColumnCountGetFilter 247 STR_IS_FILTER, // InclusiveStopFilter 248 STR_PREFIX_FILTER, // PrefixFilter 249 STR_PAGE_FILTER, // PageFilter 250 STR_SKIP_FILTER, // SkipFilter 251 STR_WHILE_FILTER, // WhileMatchFilter 252 STR_KEY_ONLY_FILTER, // KeyOnlyFilter 253 STR_FIRST_KEY_ONLY_FILTER, // FirstKeyOnlyFilter 254 STR_MCP_FILTER, // MultipleColumnPrefixFilter 255 STR_L_MCP_FILTER, // MultipleColumnPrefixFilter 256 STR_DC_FILTER, // DependentColumnFilter 257 STR_FAMILY_FILTER, // FamilyFilter 258 STR_QUALIFIER_FILTER, // QualifierFilter 259 STR_ROW_FILTER, // RowFilter 260 STR_VALUE_FILTER, // ValueFilter 261 STR_SCV_FILTER, // SingleColumnValueFilter 262 STR_SCVE_FILTER, // SingleColumnValueExcludeFilter 263 STR_AND_FILTER_LIST, // FilterList 264 STR_OR_FILTER_LIST, // FilterList 265 STR_L_FILTER_LIST, // FilterList 266 }; 267 268 static { 269 assertEquals(FILTERS.length, FILTERS_INFO.length, 270 "The sizes of static arrays do not match: " + "[FILTERS: %d <=> FILTERS_INFO: %d]"); 271 } 272 273 /** 274 * Test the client Operations' JSON encoding to ensure that produced JSON is parseable and that 275 * the details are present and not corrupted. 276 * @throws IOException if the JSON conversion fails 277 */ 278 @Test 279 public void testOperationJSON() throws IOException { 280 // produce a Scan Operation 281 Scan scan = new Scan().withStartRow(ROW); 282 scan.addColumn(FAMILY, QUALIFIER); 283 // get its JSON representation, and parse it 284 String json = scan.toJSON(); 285 Type typeOfHashMap = new TypeToken<Map<String, Object>>() { 286 }.getType(); 287 Map<String, Object> parsedJSON = GSON.fromJson(json, typeOfHashMap); 288 // check for the row 289 assertEquals(Bytes.toStringBinary(ROW), parsedJSON.get("startRow"), 290 "startRow incorrect in Scan.toJSON()"); 291 // check for the family and the qualifier. 292 List familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 293 assertNotNull(familyInfo, "Family absent in Scan.toJSON()"); 294 assertEquals(1, familyInfo.size(), "Qualifier absent in Scan.toJSON()"); 295 assertEquals(Bytes.toStringBinary(QUALIFIER), familyInfo.get(0), 296 "Qualifier incorrect in Scan.toJSON()"); 297 298 // produce a Get Operation 299 Get get = new Get(ROW); 300 get.addColumn(FAMILY, QUALIFIER); 301 // get its JSON representation, and parse it 302 json = get.toJSON(); 303 parsedJSON = GSON.fromJson(json, typeOfHashMap); 304 // check for the row 305 assertEquals(Bytes.toStringBinary(ROW), parsedJSON.get("row"), "row incorrect in Get.toJSON()"); 306 // check for the family and the qualifier. 307 familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 308 assertNotNull(familyInfo, "Family absent in Get.toJSON()"); 309 assertEquals(1, familyInfo.size(), "Qualifier absent in Get.toJSON()"); 310 assertEquals(Bytes.toStringBinary(QUALIFIER), familyInfo.get(0), 311 "Qualifier incorrect in Get.toJSON()"); 312 313 // produce a Put operation 314 Put put = new Put(ROW); 315 put.addColumn(FAMILY, QUALIFIER, VALUE); 316 // get its JSON representation, and parse it 317 json = put.toJSON(); 318 parsedJSON = GSON.fromJson(json, typeOfHashMap); 319 // check for the row 320 assertEquals(Bytes.toStringBinary(ROW), parsedJSON.get("row"), "row absent in Put.toJSON()"); 321 // check for the family and the qualifier. 322 familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 323 assertNotNull(familyInfo, "Family absent in Put.toJSON()"); 324 assertEquals(1, familyInfo.size(), "KeyValue absent in Put.toJSON()"); 325 Map kvMap = (Map) familyInfo.get(0); 326 assertEquals(Bytes.toStringBinary(QUALIFIER), kvMap.get("qualifier"), 327 "Qualifier incorrect in Put.toJSON()"); 328 assertEquals(VALUE.length, ((Number) kvMap.get("vlen")).intValue(), 329 "Value length incorrect in Put.toJSON()"); 330 331 // produce a Delete operation 332 Delete delete = new Delete(ROW); 333 delete.addColumn(FAMILY, QUALIFIER); 334 // get its JSON representation, and parse it 335 json = delete.toJSON(); 336 parsedJSON = GSON.fromJson(json, typeOfHashMap); 337 // check for the row 338 assertEquals(Bytes.toStringBinary(ROW), parsedJSON.get("row"), "row absent in Delete.toJSON()"); 339 // check for the family and the qualifier. 340 familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 341 assertNotNull(familyInfo, "Family absent in Delete.toJSON()"); 342 assertEquals(1, familyInfo.size(), "KeyValue absent in Delete.toJSON()"); 343 kvMap = (Map) familyInfo.get(0); 344 assertEquals(Bytes.toStringBinary(QUALIFIER), kvMap.get("qualifier"), 345 "Qualifier incorrect in Delete.toJSON()"); 346 } 347 348 /** 349 * Test the client Scan Operations' JSON encoding to ensure that produced JSON is parseable and 350 * that the details are present and not corrupted. 351 * @throws IOException if the JSON conversion fails 352 */ 353 @Test 354 public void testScanOperationToJSON() throws IOException { 355 // produce a Scan Operation 356 Scan scan = new Scan().withStartRow(ROW, true); 357 scan.addColumn(FAMILY, QUALIFIER); 358 scan.withStopRow(ROW, true); 359 scan.readVersions(5); 360 scan.setBatch(10); 361 scan.setAllowPartialResults(true); 362 scan.setMaxResultsPerColumnFamily(3); 363 scan.setRowOffsetPerColumnFamily(8); 364 scan.setCaching(20); 365 scan.setMaxResultSize(50); 366 scan.setCacheBlocks(true); 367 scan.setReversed(true); 368 scan.setTimeRange(1000, 2000); 369 scan.setAsyncPrefetch(true); 370 scan.setMvccReadPoint(123); 371 scan.setLimit(5); 372 scan.setReadType(Scan.ReadType.PREAD); 373 scan.setNeedCursorResult(true); 374 scan.setFilter(SCV_FILTER); 375 scan.setReplicaId(1); 376 scan.setConsistency(Consistency.STRONG); 377 scan.setLoadColumnFamiliesOnDemand(true); 378 scan.setColumnFamilyTimeRange(FAMILY, 2000, 3000); 379 scan.setPriority(10); 380 381 // get its JSON representation, and parse it 382 String json = scan.toJSON(); 383 Type typeOfHashMap = new TypeToken<Map<String, Object>>() { 384 }.getType(); 385 Gson gson = new GsonBuilder().setLongSerializationPolicy(LongSerializationPolicy.STRING) 386 .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create(); 387 Map<String, Object> parsedJSON = gson.fromJson(json, typeOfHashMap); 388 // check for the row 389 assertEquals(Bytes.toStringBinary(ROW), parsedJSON.get("startRow"), 390 "startRow incorrect in Scan.toJSON()"); 391 // check for the family and the qualifier. 392 List familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 393 assertNotNull(familyInfo, "Family absent in Scan.toJSON()"); 394 assertEquals(1, familyInfo.size(), "Qualifier absent in Scan.toJSON()"); 395 assertEquals(Bytes.toStringBinary(QUALIFIER), familyInfo.get(0), 396 "Qualifier incorrect in Scan.toJSON()"); 397 assertEquals(Bytes.toStringBinary(ROW), parsedJSON.get("stopRow"), 398 "stopRow incorrect in Scan.toJSON()"); 399 assertEquals(true, parsedJSON.get("includeStartRow"), 400 "includeStartRow incorrect in Scan.toJSON()"); 401 assertEquals(true, parsedJSON.get("includeStopRow"), 402 "includeStopRow incorrect in Scan.toJSON()"); 403 assertEquals(5L, parsedJSON.get("maxVersions"), "maxVersions incorrect in Scan.toJSON()"); 404 assertEquals(10L, parsedJSON.get("batch"), "batch incorrect in Scan.toJSON()"); 405 assertEquals(true, parsedJSON.get("allowPartialResults"), 406 "allowPartialResults incorrect in Scan.toJSON()"); 407 assertEquals(3L, parsedJSON.get("storeLimit"), "storeLimit incorrect in Scan.toJSON()"); 408 assertEquals(8L, parsedJSON.get("storeOffset"), "storeOffset incorrect in Scan.toJSON()"); 409 assertEquals(20L, parsedJSON.get("caching"), "caching incorrect in Scan.toJSON()"); 410 assertEquals("50", parsedJSON.get("maxResultSize"), "maxResultSize incorrect in Scan.toJSON()"); 411 assertEquals(true, parsedJSON.get("cacheBlocks"), "cacheBlocks incorrect in Scan.toJSON()"); 412 assertEquals(true, parsedJSON.get("reversed"), "reversed incorrect in Scan.toJSON()"); 413 List trList = (List) parsedJSON.get("timeRange"); 414 assertEquals(2, trList.size(), "timeRange incorrect in Scan.toJSON()"); 415 assertEquals("1000", trList.get(0), "timeRange incorrect in Scan.toJSON()"); 416 assertEquals("2000", trList.get(1), "timeRange incorrect in Scan.toJSON()"); 417 418 assertEquals(true, parsedJSON.get("asyncPrefetch"), "asyncPrefetch incorrect in Scan.toJSON()"); 419 assertEquals("123", parsedJSON.get("mvccReadPoint"), 420 "mvccReadPoint incorrect in Scan.toJSON()"); 421 assertEquals(5L, parsedJSON.get("limit"), "limit incorrect in Scan.toJSON()"); 422 assertEquals("PREAD", parsedJSON.get("readType"), "readType incorrect in Scan.toJSON()"); 423 assertEquals(true, parsedJSON.get("needCursorResult"), 424 "needCursorResult incorrect in Scan.toJSON()"); 425 426 Map colFamTimeRange = (Map) parsedJSON.get("colFamTimeRangeMap"); 427 assertEquals(1L, colFamTimeRange.size(), "colFamTimeRangeMap incorrect in Scan.toJSON()"); 428 List testFamily = (List) colFamTimeRange.get("testFamily"); 429 assertEquals(2L, testFamily.size(), "colFamTimeRangeMap incorrect in Scan.toJSON()"); 430 assertEquals("2000", testFamily.get(0), "colFamTimeRangeMap incorrect in Scan.toJSON()"); 431 assertEquals("3000", testFamily.get(1), "colFamTimeRangeMap incorrect in Scan.toJSON()"); 432 433 assertEquals(1L, parsedJSON.get("targetReplicaId"), 434 "targetReplicaId incorrect in Scan.toJSON()"); 435 assertEquals("STRONG", parsedJSON.get("consistency"), "consistency incorrect in Scan.toJSON()"); 436 assertEquals(true, parsedJSON.get("loadColumnFamiliesOnDemand"), 437 "loadColumnFamiliesOnDemand incorrect in Scan.toJSON()"); 438 439 assertEquals(10L, parsedJSON.get("priority"), "priority incorrect in Scan.toJSON()"); 440 441 } 442 443 @Test 444 public void testPutCreationWithByteBuffer() { 445 Put p = new Put(ROW); 446 List<Cell> c = p.get(FAMILY, QUALIFIER); 447 assertEquals(0, c.size()); 448 assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 449 450 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 1984L, ByteBuffer.wrap(VALUE)); 451 c = p.get(FAMILY, QUALIFIER); 452 assertEquals(1, c.size()); 453 assertEquals(1984L, c.get(0).getTimestamp()); 454 assertArrayEquals(VALUE, CellUtil.cloneValue(c.get(0))); 455 assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 456 assertEquals(0, 457 CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue((ExtendedCell) c.get(0)))); 458 459 p = new Put(ROW); 460 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 2013L, null); 461 c = p.get(FAMILY, QUALIFIER); 462 assertEquals(1, c.size()); 463 assertEquals(2013L, c.get(0).getTimestamp()); 464 assertArrayEquals(new byte[] {}, CellUtil.cloneValue(c.get(0))); 465 assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 466 assertEquals(0, 467 CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue((ExtendedCell) c.get(0)))); 468 469 p = new Put(ByteBuffer.wrap(ROW)); 470 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null); 471 c = p.get(FAMILY, QUALIFIER); 472 assertEquals(1, c.size()); 473 assertEquals(2001L, c.get(0).getTimestamp()); 474 assertArrayEquals(new byte[] {}, CellUtil.cloneValue(c.get(0))); 475 assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0))); 476 assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 477 assertEquals(0, 478 CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue((ExtendedCell) c.get(0)))); 479 480 p = new Put(ByteBuffer.wrap(ROW), 1970L); 481 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null); 482 c = p.get(FAMILY, QUALIFIER); 483 assertEquals(1, c.size()); 484 assertEquals(2001L, c.get(0).getTimestamp()); 485 assertArrayEquals(new byte[] {}, CellUtil.cloneValue(c.get(0))); 486 assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0))); 487 assertEquals(1970L, p.getTimestamp()); 488 assertEquals(0, 489 CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue((ExtendedCell) c.get(0)))); 490 } 491 492 @Test 493 @SuppressWarnings("rawtypes") 494 public void testOperationSubClassMethodsAreBuilderStyle() { 495 /* 496 * All Operation subclasses should have a builder style setup where setXXX/addXXX methods can be 497 * chainable together: . For example: Scan scan = new Scan() .setFoo(foo) .setBar(bar) 498 * .setBuz(buz) This test ensures that all methods starting with "set" returns the declaring 499 * object 500 */ 501 502 // TODO: We should ensure all subclasses of Operation is checked. 503 Class[] classes = new Class[] { Operation.class, OperationWithAttributes.class, Mutation.class, 504 Query.class, Delete.class, Increment.class, Append.class, Put.class, Get.class, Scan.class }; 505 506 BuilderStyleTest.assertClassesAreBuilderStyle(classes); 507 } 508 509 /** 510 * Test the client Get Operations' JSON encoding to ensure that produced JSON is parseable and 511 * that the details are present and not corrupted. 512 * @throws IOException if the JSON conversion fails 513 */ 514 @Test 515 public void testGetOperationToJSON() throws IOException { 516 // produce a Scan Operation 517 Get get = new Get(ROW); 518 get.addColumn(FAMILY, QUALIFIER); 519 get.readVersions(5); 520 get.setMaxResultsPerColumnFamily(3); 521 get.setRowOffsetPerColumnFamily(8); 522 get.setCacheBlocks(true); 523 get.setMaxResultsPerColumnFamily(5); 524 get.setRowOffsetPerColumnFamily(9); 525 get.setCheckExistenceOnly(true); 526 get.setTimeRange(1000, 2000); 527 get.setFilter(SCV_FILTER); 528 get.setReplicaId(1); 529 get.setConsistency(Consistency.STRONG); 530 get.setLoadColumnFamiliesOnDemand(true); 531 get.setColumnFamilyTimeRange(FAMILY, 2000, 3000); 532 get.setPriority(10); 533 534 // get its JSON representation, and parse it 535 String json = get.toJSON(); 536 Type typeOfHashMap = new TypeToken<Map<String, Object>>() { 537 }.getType(); 538 Gson gson = new GsonBuilder().setLongSerializationPolicy(LongSerializationPolicy.STRING) 539 .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create(); 540 Map<String, Object> parsedJSON = gson.fromJson(json, typeOfHashMap); 541 // check for the row 542 assertEquals(Bytes.toStringBinary(ROW), parsedJSON.get("row"), "row incorrect in Get.toJSON()"); 543 // check for the family and the qualifier. 544 List familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 545 assertNotNull(familyInfo, "Family absent in Get.toJSON()"); 546 assertEquals(1, familyInfo.size(), "Qualifier absent in Get.toJSON()"); 547 assertEquals(Bytes.toStringBinary(QUALIFIER), familyInfo.get(0), 548 "Qualifier incorrect in Get.toJSON()"); 549 550 assertEquals(5L, parsedJSON.get("maxVersions"), "maxVersions incorrect in Get.toJSON()"); 551 552 assertEquals(5L, parsedJSON.get("storeLimit"), "storeLimit incorrect in Get.toJSON()"); 553 assertEquals(9L, parsedJSON.get("storeOffset"), "storeOffset incorrect in Get.toJSON()"); 554 555 assertEquals(true, parsedJSON.get("cacheBlocks"), "cacheBlocks incorrect in Get.toJSON()"); 556 557 List trList = (List) parsedJSON.get("timeRange"); 558 assertEquals(2, trList.size(), "timeRange incorrect in Get.toJSON()"); 559 assertEquals("1000", trList.get(0), "timeRange incorrect in Get.toJSON()"); 560 assertEquals("2000", trList.get(1), "timeRange incorrect in Get.toJSON()"); 561 562 Map colFamTimeRange = (Map) parsedJSON.get("colFamTimeRangeMap"); 563 assertEquals(1L, colFamTimeRange.size(), "colFamTimeRangeMap incorrect in Get.toJSON()"); 564 List testFamily = (List) colFamTimeRange.get("testFamily"); 565 assertEquals(2L, testFamily.size(), "colFamTimeRangeMap incorrect in Get.toJSON()"); 566 assertEquals("2000", testFamily.get(0), "colFamTimeRangeMap incorrect in Get.toJSON()"); 567 assertEquals("3000", testFamily.get(1), "colFamTimeRangeMap incorrect in Get.toJSON()"); 568 569 assertEquals(1L, parsedJSON.get("targetReplicaId"), 570 "targetReplicaId incorrect in Get.toJSON()"); 571 assertEquals("STRONG", parsedJSON.get("consistency"), "consistency incorrect in Get.toJSON()"); 572 assertEquals(true, parsedJSON.get("loadColumnFamiliesOnDemand"), 573 "loadColumnFamiliesOnDemand incorrect in Get.toJSON()"); 574 575 assertEquals(10L, parsedJSON.get("priority"), "priority incorrect in Get.toJSON()"); 576 assertEquals(true, parsedJSON.get("checkExistenceOnly"), 577 "checkExistenceOnly incorrect in Get.toJSON()"); 578 579 } 580}