View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.client;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertNotNull;
23  
24  import java.io.IOException;
25  import java.nio.ByteBuffer;
26  import java.util.Arrays;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.apache.hadoop.hbase.Cell;
32  import org.apache.hadoop.hbase.CellUtil;
33  import org.apache.hadoop.hbase.HConstants;
34  import org.apache.hadoop.hbase.KeyValue;
35  import org.apache.hadoop.hbase.filter.BinaryComparator;
36  import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
37  import org.apache.hadoop.hbase.filter.ColumnPaginationFilter;
38  import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;
39  import org.apache.hadoop.hbase.filter.ColumnRangeFilter;
40  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
41  import org.apache.hadoop.hbase.filter.DependentColumnFilter;
42  import org.apache.hadoop.hbase.filter.FamilyFilter;
43  import org.apache.hadoop.hbase.filter.Filter;
44  import org.apache.hadoop.hbase.filter.FilterList;
45  import org.apache.hadoop.hbase.filter.FilterList.Operator;
46  import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
47  import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
48  import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
49  import org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter;
50  import org.apache.hadoop.hbase.filter.PageFilter;
51  import org.apache.hadoop.hbase.filter.PrefixFilter;
52  import org.apache.hadoop.hbase.filter.QualifierFilter;
53  import org.apache.hadoop.hbase.filter.RowFilter;
54  import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter;
55  import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
56  import org.apache.hadoop.hbase.filter.SkipFilter;
57  import org.apache.hadoop.hbase.filter.TimestampsFilter;
58  import org.apache.hadoop.hbase.filter.ValueFilter;
59  import org.apache.hadoop.hbase.filter.WhileMatchFilter;
60  import org.apache.hadoop.hbase.testclassification.SmallTests;
61  import org.apache.hadoop.hbase.util.BuilderStyleTest;
62  import org.apache.hadoop.hbase.util.Bytes;
63  import org.codehaus.jackson.map.ObjectMapper;
64  import org.junit.Assert;
65  import org.junit.Test;
66  import org.junit.experimental.categories.Category;
67  
68  /**
69   * Run tests that use the functionality of the Operation superclass for
70   * Puts, Gets, Deletes, Scans, and MultiPuts.
71   */
72  @Category(SmallTests.class)
73  public class TestOperation {
74    private static byte [] ROW = Bytes.toBytes("testRow");
75    private static byte [] FAMILY = Bytes.toBytes("testFamily");
76    private static byte [] QUALIFIER = Bytes.toBytes("testQualifier");
77    private static byte [] VALUE = Bytes.toBytes("testValue");
78  
79    private static ObjectMapper mapper = new ObjectMapper();
80  
81    private static List<Long> TS_LIST = Arrays.asList(2L, 3L, 5L);
82    private static TimestampsFilter TS_FILTER = new TimestampsFilter(TS_LIST);
83    private static String STR_TS_FILTER = TS_FILTER.getClass().getSimpleName() + " (3/3): [2, 3, 5]";
84  
85    private static List<Long> L_TS_LIST = Arrays.asList(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L);
86    private static TimestampsFilter L_TS_FILTER = new TimestampsFilter(L_TS_LIST);
87    private static String STR_L_TS_FILTER =
88        L_TS_FILTER.getClass().getSimpleName() + " (5/11): [0, 1, 2, 3, 4]";
89  
90    private static String COL_NAME_1 = "col1";
91    private static ColumnPrefixFilter COL_PRE_FILTER =
92        new ColumnPrefixFilter(Bytes.toBytes(COL_NAME_1));
93    private static String STR_COL_PRE_FILTER =
94        COL_PRE_FILTER.getClass().getSimpleName() + " " + COL_NAME_1;
95  
96    private static String COL_NAME_2 = "col2";
97    private static ColumnRangeFilter CR_FILTER =
98        new ColumnRangeFilter(Bytes.toBytes(COL_NAME_1), true, Bytes.toBytes(COL_NAME_2), false);
99    private static String STR_CR_FILTER = CR_FILTER.getClass().getSimpleName()
100       + " [" + COL_NAME_1 + ", " + COL_NAME_2 + ")";
101 
102   private static int COL_COUNT = 9;
103   private static ColumnCountGetFilter CCG_FILTER = new ColumnCountGetFilter(COL_COUNT);
104   private static String STR_CCG_FILTER = CCG_FILTER.getClass().getSimpleName() + " " + COL_COUNT;
105 
106   private static int LIMIT = 3;
107   private static int OFFSET = 4;
108   private static ColumnPaginationFilter CP_FILTER = new ColumnPaginationFilter(LIMIT, OFFSET);
109   private static String STR_CP_FILTER = CP_FILTER.getClass().getSimpleName()
110       + " (" + LIMIT + ", " + OFFSET + ")";
111 
112   private static String STOP_ROW_KEY = "stop";
113   private static InclusiveStopFilter IS_FILTER =
114       new InclusiveStopFilter(Bytes.toBytes(STOP_ROW_KEY));
115   private static String STR_IS_FILTER =
116       IS_FILTER.getClass().getSimpleName() + " " + STOP_ROW_KEY;
117 
118   private static String PREFIX = "prefix";
119   private static PrefixFilter PREFIX_FILTER = new PrefixFilter(Bytes.toBytes(PREFIX));
120   private static String STR_PREFIX_FILTER = "PrefixFilter " + PREFIX;
121 
122   private static byte[][] PREFIXES = { Bytes.toBytes("0"), Bytes.toBytes("1"), Bytes.toBytes("2") };
123   private static MultipleColumnPrefixFilter MCP_FILTER = new MultipleColumnPrefixFilter(PREFIXES);
124   private static String STR_MCP_FILTER =
125       MCP_FILTER.getClass().getSimpleName() + " (3/3): [0, 1, 2]";
126 
127   private static byte[][] L_PREFIXES = {
128     Bytes.toBytes("0"), Bytes.toBytes("1"), Bytes.toBytes("2"), Bytes.toBytes("3"),
129     Bytes.toBytes("4"), Bytes.toBytes("5"), Bytes.toBytes("6"), Bytes.toBytes("7") };
130   private static MultipleColumnPrefixFilter L_MCP_FILTER =
131       new MultipleColumnPrefixFilter(L_PREFIXES);
132   private static String STR_L_MCP_FILTER =
133       L_MCP_FILTER.getClass().getSimpleName() + " (5/8): [0, 1, 2, 3, 4]";
134 
135   private static int PAGE_SIZE = 9;
136   private static PageFilter PAGE_FILTER = new PageFilter(PAGE_SIZE);
137   private static String STR_PAGE_FILTER = PAGE_FILTER.getClass().getSimpleName() + " " + PAGE_SIZE;
138 
139   private static SkipFilter SKIP_FILTER = new SkipFilter(L_TS_FILTER);
140   private static String STR_SKIP_FILTER =
141       SKIP_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER;
142 
143   private static WhileMatchFilter WHILE_FILTER = new WhileMatchFilter(L_TS_FILTER);
144   private static String STR_WHILE_FILTER =
145       WHILE_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER;
146 
147   private static KeyOnlyFilter KEY_ONLY_FILTER = new KeyOnlyFilter();
148   private static String STR_KEY_ONLY_FILTER = KEY_ONLY_FILTER.getClass().getSimpleName();
149 
150   private static FirstKeyOnlyFilter FIRST_KEY_ONLY_FILTER = new FirstKeyOnlyFilter();
151   private static String STR_FIRST_KEY_ONLY_FILTER =
152       FIRST_KEY_ONLY_FILTER.getClass().getSimpleName();
153 
154   private static CompareOp CMP_OP = CompareOp.EQUAL;
155   private static byte[] CMP_VALUE = Bytes.toBytes("value");
156   private static BinaryComparator BC = new BinaryComparator(CMP_VALUE);
157   private static DependentColumnFilter DC_FILTER =
158       new DependentColumnFilter(FAMILY, QUALIFIER, true, CMP_OP, BC);
159   private static String STR_DC_FILTER = String.format(
160       "%s (%s, %s, %s, %s, %s)", DC_FILTER.getClass().getSimpleName(),
161       Bytes.toStringBinary(FAMILY), Bytes.toStringBinary(QUALIFIER), true,
162       CMP_OP.name(), Bytes.toStringBinary(BC.getValue()));
163 
164   private static FamilyFilter FAMILY_FILTER = new FamilyFilter(CMP_OP, BC);
165   private static String STR_FAMILY_FILTER =
166       FAMILY_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
167 
168   private static QualifierFilter QUALIFIER_FILTER = new QualifierFilter(CMP_OP, BC);
169   private static String STR_QUALIFIER_FILTER =
170       QUALIFIER_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
171 
172   private static RowFilter ROW_FILTER = new RowFilter(CMP_OP, BC);
173   private static String STR_ROW_FILTER = ROW_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
174 
175   private static ValueFilter VALUE_FILTER = new ValueFilter(CMP_OP, BC);
176   private static String STR_VALUE_FILTER =
177       VALUE_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
178 
179   private static SingleColumnValueFilter SCV_FILTER =
180       new SingleColumnValueFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE);
181   private static String STR_SCV_FILTER = String.format("%s (%s, %s, %s, %s)",
182       SCV_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY),
183       Bytes.toStringBinary(QUALIFIER), CMP_OP.name(),
184       Bytes.toStringBinary(CMP_VALUE));
185 
186   private static SingleColumnValueExcludeFilter SCVE_FILTER =
187       new SingleColumnValueExcludeFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE);
188   private static String STR_SCVE_FILTER = String.format("%s (%s, %s, %s, %s)",
189       SCVE_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY),
190       Bytes.toStringBinary(QUALIFIER), CMP_OP.name(), Bytes.toStringBinary(CMP_VALUE));
191 
192   private static FilterList AND_FILTER_LIST = new FilterList(
193       Operator.MUST_PASS_ALL, Arrays.asList((Filter) TS_FILTER, L_TS_FILTER, CR_FILTER));
194   private static String STR_AND_FILTER_LIST = String.format(
195       "%s AND (3/3): [%s, %s, %s]", AND_FILTER_LIST.getClass().getSimpleName(),
196       STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER);
197 
198   private static FilterList OR_FILTER_LIST = new FilterList(
199       Operator.MUST_PASS_ONE, Arrays.asList((Filter) TS_FILTER, L_TS_FILTER, CR_FILTER));
200   private static String STR_OR_FILTER_LIST = String.format(
201       "%s OR (3/3): [%s, %s, %s]", AND_FILTER_LIST.getClass().getSimpleName(),
202       STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER);
203 
204   private static FilterList L_FILTER_LIST = new FilterList(
205       Arrays.asList((Filter) TS_FILTER, L_TS_FILTER, CR_FILTER, COL_PRE_FILTER,
206           CCG_FILTER, CP_FILTER, PREFIX_FILTER, PAGE_FILTER));
207   private static String STR_L_FILTER_LIST = String.format(
208       "%s AND (5/8): [%s, %s, %s, %s, %s, %s]",
209       L_FILTER_LIST.getClass().getSimpleName(), STR_TS_FILTER, STR_L_TS_FILTER,
210       STR_CR_FILTER, STR_COL_PRE_FILTER, STR_CCG_FILTER, STR_CP_FILTER);
211 
212   private static Filter[] FILTERS = {
213     TS_FILTER,             // TimestampsFilter
214     L_TS_FILTER,           // TimestampsFilter
215     COL_PRE_FILTER,        // ColumnPrefixFilter
216     CP_FILTER,             // ColumnPaginationFilter
217     CR_FILTER,             // ColumnRangeFilter
218     CCG_FILTER,            // ColumnCountGetFilter
219     IS_FILTER,             // InclusiveStopFilter
220     PREFIX_FILTER,         // PrefixFilter
221     PAGE_FILTER,           // PageFilter
222     SKIP_FILTER,           // SkipFilter
223     WHILE_FILTER,          // WhileMatchFilter
224     KEY_ONLY_FILTER,       // KeyOnlyFilter
225     FIRST_KEY_ONLY_FILTER, // FirstKeyOnlyFilter
226     MCP_FILTER,            // MultipleColumnPrefixFilter
227     L_MCP_FILTER,          // MultipleColumnPrefixFilter
228     DC_FILTER,             // DependentColumnFilter
229     FAMILY_FILTER,         // FamilyFilter
230     QUALIFIER_FILTER,      // QualifierFilter
231     ROW_FILTER,            // RowFilter
232     VALUE_FILTER,          // ValueFilter
233     SCV_FILTER,            // SingleColumnValueFilter
234     SCVE_FILTER,           // SingleColumnValueExcludeFilter
235     AND_FILTER_LIST,       // FilterList
236     OR_FILTER_LIST,        // FilterList
237     L_FILTER_LIST,         // FilterList
238   };
239 
240   private static String[] FILTERS_INFO = {
241     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: "
270         + "[FILTERS: %d <=> FILTERS_INFO: %d]",
271         FILTERS.length, FILTERS_INFO.length);
272   }
273 
274   /**
275    * Test the client Operations' JSON encoding to ensure that produced JSON is
276    * parseable and that the details are present and not corrupted.
277    * @throws IOException
278    */
279   @Test
280   public void testOperationJSON()
281       throws IOException {
282     // produce a Scan Operation
283     Scan scan = new Scan(ROW);
284     scan.addColumn(FAMILY, QUALIFIER);
285     // get its JSON representation, and parse it
286     String json = scan.toJSON();
287     Map<String, Object> parsedJSON = mapper.readValue(json, HashMap.class);
288     // check for the row
289     assertEquals("startRow incorrect in Scan.toJSON()",
290         Bytes.toStringBinary(ROW), parsedJSON.get("startRow"));
291     // check for the family and the qualifier.
292     List familyInfo = (List) ((Map) parsedJSON.get("families")).get(
293         Bytes.toStringBinary(FAMILY));
294     assertNotNull("Family absent in Scan.toJSON()", familyInfo);
295     assertEquals("Qualifier absent in Scan.toJSON()", 1, familyInfo.size());
296     assertEquals("Qualifier incorrect in Scan.toJSON()",
297         Bytes.toStringBinary(QUALIFIER),
298         familyInfo.get(0));
299 
300     // produce a Get Operation
301     Get get = new Get(ROW);
302     get.addColumn(FAMILY, QUALIFIER);
303     // get its JSON representation, and parse it
304     json = get.toJSON();
305     parsedJSON = mapper.readValue(json, HashMap.class);
306     // check for the row
307     assertEquals("row incorrect in Get.toJSON()",
308         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
309     // check for the family and the qualifier.
310     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
311         Bytes.toStringBinary(FAMILY));
312     assertNotNull("Family absent in Get.toJSON()", familyInfo);
313     assertEquals("Qualifier absent in Get.toJSON()", 1, familyInfo.size());
314     assertEquals("Qualifier incorrect in Get.toJSON()",
315         Bytes.toStringBinary(QUALIFIER),
316         familyInfo.get(0));
317 
318     // produce a Put operation
319     Put put = new Put(ROW);
320     put.add(FAMILY, QUALIFIER, VALUE);
321     // get its JSON representation, and parse it
322     json = put.toJSON();
323     parsedJSON = mapper.readValue(json, HashMap.class);
324     // check for the row
325     assertEquals("row absent in Put.toJSON()",
326         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
327     // check for the family and the qualifier.
328     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
329         Bytes.toStringBinary(FAMILY));
330     assertNotNull("Family absent in Put.toJSON()", familyInfo);
331     assertEquals("KeyValue absent in Put.toJSON()", 1, familyInfo.size());
332     Map kvMap = (Map) familyInfo.get(0);
333     assertEquals("Qualifier incorrect in Put.toJSON()",
334         Bytes.toStringBinary(QUALIFIER),
335         kvMap.get("qualifier"));
336     assertEquals("Value length incorrect in Put.toJSON()",
337         VALUE.length, kvMap.get("vlen"));
338 
339     // produce a Delete operation
340     Delete delete = new Delete(ROW);
341     delete.deleteColumn(FAMILY, QUALIFIER);
342     // get its JSON representation, and parse it
343     json = delete.toJSON();
344     parsedJSON = mapper.readValue(json, HashMap.class);
345     // check for the row
346     assertEquals("row absent in Delete.toJSON()",
347         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
348     // check for the family and the qualifier.
349     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
350         Bytes.toStringBinary(FAMILY));
351     assertNotNull("Family absent in Delete.toJSON()", familyInfo);
352     assertEquals("KeyValue absent in Delete.toJSON()", 1, familyInfo.size());
353     kvMap = (Map) familyInfo.get(0);
354     assertEquals("Qualifier incorrect in Delete.toJSON()",
355         Bytes.toStringBinary(QUALIFIER), kvMap.get("qualifier"));
356   }
357 
358   @Test
359   public void testPutCreationWithByteBuffer() {
360     Put p = new Put(ROW);
361     List<Cell> c = p.get(FAMILY, QUALIFIER);
362     Assert.assertEquals(0, c.size());
363     Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
364 
365     p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 1984L, ByteBuffer.wrap(VALUE));
366     c = p.get(FAMILY, QUALIFIER);
367     Assert.assertEquals(1, c.size());
368     Assert.assertEquals(1984L, c.get(0).getTimestamp());
369     Assert.assertArrayEquals(VALUE, CellUtil.cloneValue(c.get(0)));
370     Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
371     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
372 
373     p = new Put(ROW);
374     p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2013L, null);
375     c = p.get(FAMILY, QUALIFIER);
376     Assert.assertEquals(1, c.size());
377     Assert.assertEquals(2013L, c.get(0).getTimestamp());
378     Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
379     Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
380     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
381 
382     p = new Put(ByteBuffer.wrap(ROW));
383     p.add(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(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
390     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
391 
392     p = new Put(ByteBuffer.wrap(ROW), 1970L);
393     p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null);
394     c = p.get(FAMILY, QUALIFIER);
395     Assert.assertEquals(1, c.size());
396     Assert.assertEquals(2001L, c.get(0).getTimestamp());
397     Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
398     Assert.assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0)));
399     Assert.assertEquals(1970L, p.getTimeStamp());
400     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
401   }
402 
403   @Test
404   @SuppressWarnings("rawtypes")
405   public void testOperationSubClassMethodsAreBuilderStyle() {
406     /* All Operation subclasses should have a builder style setup where setXXX/addXXX methods
407      * can be chainable together:
408      * . For example:
409      * Scan scan = new Scan()
410      *     .setFoo(foo)
411      *     .setBar(bar)
412      *     .setBuz(buz)
413      *
414      * This test ensures that all methods starting with "set" returns the declaring object
415      */
416 
417     // TODO: We should ensure all subclasses of Operation is checked.
418     Class[] classes = new Class[] {
419         Operation.class,
420         OperationWithAttributes.class,
421         Mutation.class,
422         Query.class,
423         Delete.class,
424         Increment.class,
425         Append.class,
426         Put.class,
427         Get.class,
428         Scan.class};
429 
430     BuilderStyleTest.assertClassesAreBuilderStyle(classes);
431   }
432 
433 }