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.Assert.assertEquals; 021import static org.junit.Assert.assertNotNull; 022 023import java.io.IOException; 024import java.lang.reflect.Type; 025import java.nio.ByteBuffer; 026import java.util.Arrays; 027import java.util.List; 028import java.util.Map; 029import org.apache.hadoop.hbase.Cell; 030import org.apache.hadoop.hbase.CellComparatorImpl; 031import org.apache.hadoop.hbase.CellUtil; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HConstants; 034import org.apache.hadoop.hbase.KeyValue; 035import org.apache.hadoop.hbase.filter.BinaryComparator; 036import org.apache.hadoop.hbase.filter.ColumnCountGetFilter; 037import org.apache.hadoop.hbase.filter.ColumnPaginationFilter; 038import org.apache.hadoop.hbase.filter.ColumnPrefixFilter; 039import org.apache.hadoop.hbase.filter.ColumnRangeFilter; 040import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; 041import org.apache.hadoop.hbase.filter.DependentColumnFilter; 042import org.apache.hadoop.hbase.filter.FamilyFilter; 043import org.apache.hadoop.hbase.filter.Filter; 044import org.apache.hadoop.hbase.filter.FilterList; 045import org.apache.hadoop.hbase.filter.FilterList.Operator; 046import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter; 047import org.apache.hadoop.hbase.filter.InclusiveStopFilter; 048import org.apache.hadoop.hbase.filter.KeyOnlyFilter; 049import org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter; 050import org.apache.hadoop.hbase.filter.PageFilter; 051import org.apache.hadoop.hbase.filter.PrefixFilter; 052import org.apache.hadoop.hbase.filter.QualifierFilter; 053import org.apache.hadoop.hbase.filter.RowFilter; 054import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter; 055import org.apache.hadoop.hbase.filter.SingleColumnValueFilter; 056import org.apache.hadoop.hbase.filter.SkipFilter; 057import org.apache.hadoop.hbase.filter.TimestampsFilter; 058import org.apache.hadoop.hbase.filter.ValueFilter; 059import org.apache.hadoop.hbase.filter.WhileMatchFilter; 060import org.apache.hadoop.hbase.testclassification.ClientTests; 061import org.apache.hadoop.hbase.testclassification.SmallTests; 062import org.apache.hadoop.hbase.util.BuilderStyleTest; 063import org.apache.hadoop.hbase.util.Bytes; 064import org.apache.hadoop.hbase.util.GsonUtil; 065import org.junit.Assert; 066import org.junit.ClassRule; 067import org.junit.Test; 068import org.junit.experimental.categories.Category; 069 070import org.apache.hbase.thirdparty.com.google.common.reflect.TypeToken; 071import org.apache.hbase.thirdparty.com.google.gson.Gson; 072 073/** 074 * Run tests that use the functionality of the Operation superclass for Puts, Gets, Deletes, Scans, 075 * and MultiPuts. 076 */ 077@Category({ ClientTests.class, SmallTests.class }) 078public class TestOperation { 079 @ClassRule 080 public static final HBaseClassTestRule CLASS_RULE = 081 HBaseClassTestRule.forClass(TestOperation.class); 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 CompareOp CMP_OP = CompareOp.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("The sizes of static arrays do not match: " + "[FILTERS: %d <=> FILTERS_INFO: %d]", 270 FILTERS.length, FILTERS_INFO.length); 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(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("startRow incorrect in Scan.toJSON()", Bytes.toStringBinary(ROW), 290 parsedJSON.get("startRow")); 291 // check for the family and the qualifier. 292 List familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 293 assertNotNull("Family absent in Scan.toJSON()", familyInfo); 294 assertEquals("Qualifier absent in Scan.toJSON()", 1, familyInfo.size()); 295 assertEquals("Qualifier incorrect in Scan.toJSON()", Bytes.toStringBinary(QUALIFIER), 296 familyInfo.get(0)); 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("row incorrect in Get.toJSON()", Bytes.toStringBinary(ROW), parsedJSON.get("row")); 306 // check for the family and the qualifier. 307 familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 308 assertNotNull("Family absent in Get.toJSON()", familyInfo); 309 assertEquals("Qualifier absent in Get.toJSON()", 1, familyInfo.size()); 310 assertEquals("Qualifier incorrect in Get.toJSON()", Bytes.toStringBinary(QUALIFIER), 311 familyInfo.get(0)); 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("row absent in Put.toJSON()", Bytes.toStringBinary(ROW), parsedJSON.get("row")); 321 // check for the family and the qualifier. 322 familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 323 assertNotNull("Family absent in Put.toJSON()", familyInfo); 324 assertEquals("KeyValue absent in Put.toJSON()", 1, familyInfo.size()); 325 Map kvMap = (Map) familyInfo.get(0); 326 assertEquals("Qualifier incorrect in Put.toJSON()", Bytes.toStringBinary(QUALIFIER), 327 kvMap.get("qualifier")); 328 assertEquals("Value length incorrect in Put.toJSON()", VALUE.length, 329 ((Number) kvMap.get("vlen")).intValue()); 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("row absent in Delete.toJSON()", Bytes.toStringBinary(ROW), parsedJSON.get("row")); 339 // check for the family and the qualifier. 340 familyInfo = (List) ((Map) parsedJSON.get("families")).get(Bytes.toStringBinary(FAMILY)); 341 assertNotNull("Family absent in Delete.toJSON()", familyInfo); 342 assertEquals("KeyValue absent in Delete.toJSON()", 1, familyInfo.size()); 343 kvMap = (Map) familyInfo.get(0); 344 assertEquals("Qualifier incorrect in Delete.toJSON()", Bytes.toStringBinary(QUALIFIER), 345 kvMap.get("qualifier")); 346 } 347 348 @Test 349 public void testPutCreationWithByteBuffer() { 350 Put p = new Put(ROW); 351 List<Cell> c = p.get(FAMILY, QUALIFIER); 352 Assert.assertEquals(0, c.size()); 353 Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 354 355 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 1984L, ByteBuffer.wrap(VALUE)); 356 c = p.get(FAMILY, QUALIFIER); 357 Assert.assertEquals(1, c.size()); 358 Assert.assertEquals(1984L, c.get(0).getTimestamp()); 359 Assert.assertArrayEquals(VALUE, CellUtil.cloneValue(c.get(0))); 360 Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 361 Assert.assertEquals(0, CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0)))); 362 363 p = new Put(ROW); 364 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 2013L, null); 365 c = p.get(FAMILY, QUALIFIER); 366 Assert.assertEquals(1, c.size()); 367 Assert.assertEquals(2013L, c.get(0).getTimestamp()); 368 Assert.assertArrayEquals(new byte[] {}, CellUtil.cloneValue(c.get(0))); 369 Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 370 Assert.assertEquals(0, CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0)))); 371 372 p = new Put(ByteBuffer.wrap(ROW)); 373 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null); 374 c = p.get(FAMILY, QUALIFIER); 375 Assert.assertEquals(1, c.size()); 376 Assert.assertEquals(2001L, c.get(0).getTimestamp()); 377 Assert.assertArrayEquals(new byte[] {}, CellUtil.cloneValue(c.get(0))); 378 Assert.assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0))); 379 Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimestamp()); 380 Assert.assertEquals(0, CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0)))); 381 382 p = new Put(ByteBuffer.wrap(ROW), 1970L); 383 p.addColumn(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null); 384 c = p.get(FAMILY, QUALIFIER); 385 Assert.assertEquals(1, c.size()); 386 Assert.assertEquals(2001L, c.get(0).getTimestamp()); 387 Assert.assertArrayEquals(new byte[] {}, CellUtil.cloneValue(c.get(0))); 388 Assert.assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0))); 389 Assert.assertEquals(1970L, p.getTimestamp()); 390 Assert.assertEquals(0, CellComparatorImpl.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0)))); 391 } 392 393 @Test 394 @SuppressWarnings("rawtypes") 395 public void testOperationSubClassMethodsAreBuilderStyle() { 396 /* 397 * All Operation subclasses should have a builder style setup where setXXX/addXXX methods can be 398 * chainable together: . For example: Scan scan = new Scan() .setFoo(foo) .setBar(bar) 399 * .setBuz(buz) This test ensures that all methods starting with "set" returns the declaring 400 * object 401 */ 402 403 // TODO: We should ensure all subclasses of Operation is checked. 404 Class[] classes = new Class[] { Operation.class, OperationWithAttributes.class, Mutation.class, 405 Query.class, Delete.class, Increment.class, Append.class, Put.class, Get.class, Scan.class }; 406 407 BuilderStyleTest.assertClassesAreBuilderStyle(classes); 408 } 409}