View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.security.visibility;
19  
20  import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME;
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertTrue;
23  
24  import java.io.IOException;
25  import java.io.InterruptedIOException;
26  import java.security.PrivilegedExceptionAction;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.List;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.conf.Configuration;
34  import org.apache.hadoop.hbase.Cell;
35  import org.apache.hadoop.hbase.CellScanner;
36  import org.apache.hadoop.hbase.CellUtil;
37  import org.apache.hadoop.hbase.HBaseTestingUtility;
38  import org.apache.hadoop.hbase.HColumnDescriptor;
39  import org.apache.hadoop.hbase.HConstants;
40  import org.apache.hadoop.hbase.HTableDescriptor;
41  import org.apache.hadoop.hbase.testclassification.MediumTests;
42  import org.apache.hadoop.hbase.TableName;
43  import org.apache.hadoop.hbase.client.Admin;
44  import org.apache.hadoop.hbase.client.Connection;
45  import org.apache.hadoop.hbase.client.ConnectionFactory;
46  import org.apache.hadoop.hbase.client.Delete;
47  import org.apache.hadoop.hbase.client.Get;
48  import org.apache.hadoop.hbase.client.HTable;
49  import org.apache.hadoop.hbase.client.Put;
50  import org.apache.hadoop.hbase.client.Result;
51  import org.apache.hadoop.hbase.client.ResultScanner;
52  import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
53  import org.apache.hadoop.hbase.client.Scan;
54  import org.apache.hadoop.hbase.client.Table;
55  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
56  import org.apache.hadoop.hbase.security.User;
57  import org.apache.hadoop.hbase.util.Bytes;
58  import org.junit.After;
59  import org.junit.AfterClass;
60  import org.junit.BeforeClass;
61  import org.junit.Rule;
62  import org.junit.Test;
63  import org.junit.experimental.categories.Category;
64  import org.junit.rules.TestName;
65  
66  /**
67   * Tests visibility labels with deletes
68   */
69  @Category(MediumTests.class)
70  public class TestVisibilityLabelsWithDeletes {
71    private static final Log LOG = LogFactory.getLog(TestVisibilityLabelsWithDeletes.class);
72    private static final String TOPSECRET = "TOPSECRET";
73    private static final String PUBLIC = "PUBLIC";
74    private static final String PRIVATE = "PRIVATE";
75    private static final String CONFIDENTIAL = "CONFIDENTIAL";
76    private static final String SECRET = "SECRET";
77    public static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
78    private static final byte[] row1 = Bytes.toBytes("row1");
79    private static final byte[] row2 = Bytes.toBytes("row2");
80    private final static byte[] fam = Bytes.toBytes("info");
81    private final static byte[] qual = Bytes.toBytes("qual");
82    private final static byte[] qual1 = Bytes.toBytes("qual1");
83    private final static byte[] qual2 = Bytes.toBytes("qual2");
84    private final static byte[] value = Bytes.toBytes("value");
85    private final static byte[] value1 = Bytes.toBytes("value1");
86    public static Configuration conf;
87  
88    @Rule
89    public final TestName TEST_NAME = new TestName();
90    public static User SUPERUSER;
91  
92    @BeforeClass
93    public static void setupBeforeClass() throws Exception {
94      // setup configuration
95      conf = TEST_UTIL.getConfiguration();
96      conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
97      VisibilityTestUtil.enableVisiblityLabels(conf);
98      conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
99          ScanLabelGenerator.class);
100     conf.set("hbase.superuser", "admin");
101     TEST_UTIL.startMiniCluster(2);
102     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
103 
104     // Wait for the labels table to become available
105     TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
106     addLabels();
107   }
108 
109   @AfterClass
110   public static void tearDownAfterClass() throws Exception {
111     TEST_UTIL.shutdownMiniCluster();
112   }
113 
114   @After
115   public void tearDown() throws Exception {
116   }
117 
118   @Test
119   public void testVisibilityLabelsWithDeleteColumns() throws Throwable {
120     setAuths();
121     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
122 
123     try (Table table = createTableAndWriteDataWithLabels(tableName,
124         SECRET + "&" + TOPSECRET, SECRET)) {
125       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
126         @Override
127         public Void run() throws Exception {
128           try (Connection connection = ConnectionFactory.createConnection(conf);
129                Table table = connection.getTable(tableName)) {
130             Delete d = new Delete(row1);
131             d.setCellVisibility(new CellVisibility(TOPSECRET + "&" + SECRET));
132             d.addColumns(fam, qual);
133             table.delete(d);
134           } catch (Throwable t) {
135             throw new IOException(t);
136           }
137           return null;
138         }
139       };
140       SUPERUSER.runAs(actiona);
141 
142       TEST_UTIL.getHBaseAdmin().flush(tableName);
143       Scan s = new Scan();
144       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL));
145       ResultScanner scanner = table.getScanner(s);
146       Result[] next = scanner.next(3);
147       assertTrue(next.length == 1);
148       CellScanner cellScanner = next[0].cellScanner();
149       cellScanner.advance();
150       Cell current = cellScanner.current();
151       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
152           current.getRowLength(), row2, 0, row2.length));
153 
154     }
155   }
156 
157   @Test
158   public void testVisibilityLabelsWithDeleteFamily() throws Exception {
159     setAuths();
160     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
161     try (Table table = createTableAndWriteDataWithLabels(tableName, SECRET,
162         CONFIDENTIAL + "|" + TOPSECRET);) {
163       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
164         @Override
165         public Void run() throws Exception {
166           try (Connection connection = ConnectionFactory.createConnection(conf);
167                Table table = connection.getTable(tableName)) {
168             Delete d = new Delete(row2);
169             d.setCellVisibility(new CellVisibility(TOPSECRET + "|" + CONFIDENTIAL));
170             d.addFamily(fam);
171             table.delete(d);
172           } catch (Throwable t) {
173             throw new IOException(t);
174           }
175           return null;
176         }
177       };
178       SUPERUSER.runAs(actiona);
179 
180       TEST_UTIL.getHBaseAdmin().flush(tableName);
181       Scan s = new Scan();
182       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL));
183       ResultScanner scanner = table.getScanner(s);
184       Result[] next = scanner.next(3);
185       assertTrue(next.length == 1);
186       CellScanner cellScanner = next[0].cellScanner();
187       cellScanner.advance();
188       Cell current = cellScanner.current();
189       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
190           current.getRowLength(), row1, 0, row1.length));
191     }
192   }
193 
194   @Test
195   public void testVisibilityLabelsWithDeleteFamilyVersion() throws Exception {
196     setAuths();
197     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
198     long[] ts = new long[] { 123l, 125l };
199     try (Table table = createTableAndWriteDataWithLabels(tableName, ts,
200         CONFIDENTIAL + "|" + TOPSECRET, SECRET)) {
201       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
202         @Override
203         public Void run() throws Exception {
204           try (Connection connection = ConnectionFactory.createConnection(conf);
205                Table table = connection.getTable(tableName)) {
206             Delete d = new Delete(row1);
207             d.setCellVisibility(new CellVisibility(TOPSECRET + "|" + CONFIDENTIAL));
208             d.deleteFamilyVersion(fam, 123l);
209             table.delete(d);
210           } catch (Throwable t) {
211             throw new IOException(t);
212           }
213           return null;
214         }
215       };
216       SUPERUSER.runAs(actiona);
217 
218       TEST_UTIL.getHBaseAdmin().flush(tableName);
219       Scan s = new Scan();
220       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL));
221       ResultScanner scanner = table.getScanner(s);
222       Result[] next = scanner.next(3);
223       assertTrue(next.length == 1);
224       CellScanner cellScanner = next[0].cellScanner();
225       cellScanner.advance();
226       Cell current = cellScanner.current();
227       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
228           current.getRowLength(), row2, 0, row2.length));
229     }
230   }
231 
232   @Test
233   public void testVisibilityLabelsWithDeleteColumnExactVersion() throws Exception {
234     setAuths();
235     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
236     long[] ts = new long[] { 123l, 125l };
237     try (Table table = createTableAndWriteDataWithLabels(tableName, ts,
238         CONFIDENTIAL + "|" + TOPSECRET, SECRET);) {
239       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
240         @Override
241         public Void run() throws Exception {
242           try (Connection connection = ConnectionFactory.createConnection(conf);
243                Table table = connection.getTable(tableName)) {
244             Delete d = new Delete(row1);
245             d.setCellVisibility(new CellVisibility(TOPSECRET + "|" + CONFIDENTIAL));
246             d.addColumn(fam, qual, 123l);
247             table.delete(d);
248           } catch (Throwable t) {
249             throw new IOException(t);
250           }
251           return null;
252         }
253       };
254       SUPERUSER.runAs(actiona);
255 
256       TEST_UTIL.getHBaseAdmin().flush(tableName);
257       Scan s = new Scan();
258       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL));
259       ResultScanner scanner = table.getScanner(s);
260       Result[] next = scanner.next(3);
261       assertTrue(next.length == 1);
262       CellScanner cellScanner = next[0].cellScanner();
263       cellScanner.advance();
264       Cell current = cellScanner.current();
265       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
266           current.getRowLength(), row2, 0, row2.length));
267     }
268   }
269 
270   @Test
271   public void testVisibilityLabelsWithDeleteColumnsWithMultipleVersions() throws Exception {
272     setAuths();
273     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
274     try (Table table = doPuts(tableName)) {
275       TEST_UTIL.getHBaseAdmin().flush(tableName);
276       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
277         @Override
278         public Void run() throws Exception {
279           try (Connection connection = ConnectionFactory.createConnection(conf);
280                Table table = connection.getTable(tableName)) {
281             Delete d = new Delete(row1);
282             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|(" +
283                 SECRET + "&" + TOPSECRET+")"));
284             d.addColumns(fam, qual, 125l);
285             table.delete(d);
286           } catch (Throwable t) {
287             throw new IOException(t);
288           }
289           return null;
290         }
291       };
292       SUPERUSER.runAs(actiona);
293 
294       TEST_UTIL.getHBaseAdmin().flush(tableName);
295       Scan s = new Scan();
296       s.setMaxVersions(5);
297       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
298       ResultScanner scanner = table.getScanner(s);
299       Result[] next = scanner.next(3);
300       assertTrue(next.length == 2);
301       CellScanner cellScanner = next[0].cellScanner();
302       cellScanner.advance();
303       Cell current = cellScanner.current();
304       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
305           current.getRowLength(), row1, 0, row1.length));
306       assertEquals(current.getTimestamp(), 127l);
307       cellScanner.advance();
308       current = cellScanner.current();
309       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
310           current.getRowLength(), row1, 0, row1.length));
311       assertEquals(current.getTimestamp(), 126l);
312       cellScanner.advance();
313       current = cellScanner.current();
314       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
315           current.getRowLength(), row1, 0, row1.length));
316       assertEquals(current.getTimestamp(), 125l);
317       cellScanner = next[1].cellScanner();
318       cellScanner.advance();
319       current = cellScanner.current();
320       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
321           current.getRowLength(), row2, 0, row2.length));
322     }
323   }
324 
325   @Test
326   public void testVisibilityLabelsWithDeleteColumnsWithMultipleVersionsNoTimestamp()
327       throws Exception {
328     setAuths();
329     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
330     try (Table table = doPuts(tableName)) {
331       TEST_UTIL.getHBaseAdmin().flush(tableName);
332       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
333         @Override
334         public Void run() throws Exception {
335           try (Connection connection = ConnectionFactory.createConnection(conf);
336                Table table = connection.getTable(tableName)) {
337             Delete d1 = new Delete(row1);
338             d1.setCellVisibility(new CellVisibility(CONFIDENTIAL));
339             d1.addColumns(fam, qual);
340 
341             table.delete(d1);
342 
343             Delete d2 = new Delete(row1);
344             d2.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
345             d2.addColumns(fam, qual);
346             table.delete(d2);
347 
348             Delete d3 = new Delete(row1);
349             d3.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
350                 + SECRET + "&" + TOPSECRET + ")"));
351             d3.addColumns(fam, qual);
352             table.delete(d3);
353           } catch (Throwable t) {
354             throw new IOException(t);
355           }
356           return null;
357         }
358       };
359       SUPERUSER.runAs(actiona);
360       Scan s = new Scan();
361       s.setMaxVersions(5);
362       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
363       ResultScanner scanner = table.getScanner(s);
364       Result[] next = scanner.next(3);
365       assertEquals(1, next.length);
366       CellScanner cellScanner = next[0].cellScanner();
367       cellScanner.advance();
368       Cell current = cellScanner.current();
369       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
370           current.getRowLength(), row2, 0, row2.length));
371     }
372   }
373 
374   @Test
375   public void
376     testVisibilityLabelsWithDeleteColumnsWithNoMatchVisExpWithMultipleVersionsNoTimestamp()
377       throws Exception {
378     setAuths();
379     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
380     try (Table table = doPuts(tableName)) {
381       TEST_UTIL.getHBaseAdmin().flush(tableName);
382       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
383         @Override
384         public Void run() throws Exception {
385           try (Connection connection = ConnectionFactory.createConnection(conf);
386                Table table = connection.getTable(tableName)) {
387             Delete d = new Delete(row1);
388             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
389             d.addColumns(fam, qual);
390             table.delete(d);
391 
392             d = new Delete(row1);
393             d.setCellVisibility(new CellVisibility(SECRET));
394             d.addColumns(fam, qual);
395             table.delete(d);
396 
397             d = new Delete(row1);
398             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
399                 + SECRET + "&" + TOPSECRET + ")"));
400             d.addColumns(fam, qual);
401             table.delete(d);
402           } catch (Throwable t) {
403             throw new IOException(t);
404           }
405           return null;
406         }
407       };
408       SUPERUSER.runAs(actiona);
409       Scan s = new Scan();
410       s.setMaxVersions(5);
411       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
412       ResultScanner scanner = table.getScanner(s);
413       Result[] next = scanner.next(3);
414       assertTrue(next.length == 2);
415       CellScanner cellScanner = next[0].cellScanner();
416       cellScanner.advance();
417       Cell current = cellScanner.current();
418       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
419           current.getRowLength(), row1, 0, row1.length));
420       cellScanner = next[1].cellScanner();
421       cellScanner.advance();
422       current = cellScanner.current();
423       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
424           current.getRowLength(), row2, 0, row2.length));
425     }
426   }
427 
428   @Test
429   public void testVisibilityLabelsWithDeleteFamilyWithMultipleVersionsNoTimestamp()
430       throws Exception {
431     setAuths();
432     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
433     try (Table table = doPuts(tableName)) {
434       TEST_UTIL.getHBaseAdmin().flush(tableName);
435       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
436         @Override
437         public Void run() throws Exception {
438           try (Connection connection = ConnectionFactory.createConnection(conf);
439                Table table = connection.getTable(tableName)) {
440             Delete d1 = new Delete(row1);
441             d1.setCellVisibility(new CellVisibility(CONFIDENTIAL));
442             d1.addFamily(fam);
443             table.delete(d1);
444 
445             Delete d2 = new Delete(row1);
446             d2.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
447             d2.addFamily(fam);
448             table.delete(d2);
449 
450             Delete d3 = new Delete(row1);
451             d3.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
452                 + SECRET + "&" + TOPSECRET + ")"));
453             d3.addFamily(fam);
454             table.delete(d3);
455           } catch (Throwable t) {
456             throw new IOException(t);
457           }
458           return null;
459         }
460       };
461       SUPERUSER.runAs(actiona);
462       Scan s = new Scan();
463       s.setMaxVersions(5);
464       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
465       ResultScanner scanner = table.getScanner(s);
466       Result[] next = scanner.next(3);
467       assertEquals(1, next.length);
468       CellScanner cellScanner = next[0].cellScanner();
469       cellScanner.advance();
470       Cell current = cellScanner.current();
471       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
472           current.getRowLength(), row2, 0, row2.length));
473     }
474   }
475 
476   @Test
477   public void testDeleteColumnsWithoutAndWithVisibilityLabels() throws Exception {
478     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
479     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
480     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
481     HTableDescriptor desc = new HTableDescriptor(tableName);
482     desc.addFamily(colDesc);
483     hBaseAdmin.createTable(desc);
484     try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
485       Put put = new Put(row1);
486       put.addColumn(fam, qual, value);
487       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
488       table.put(put);
489       Delete d = new Delete(row1);
490       // without visibility
491       d.addColumns(fam, qual, HConstants.LATEST_TIMESTAMP);
492       table.delete(d);
493       PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
494         @Override
495         public Void run() throws Exception {
496           try (Connection connection = ConnectionFactory.createConnection(conf);
497               Table table = connection.getTable(tableName)) {
498             Scan s = new Scan();
499             ResultScanner scanner = table.getScanner(s);
500             Result[] next = scanner.next(3);
501             assertEquals(next.length, 1);
502           } catch (Throwable t) {
503             throw new IOException(t);
504           }
505           return null;
506         }
507       };
508       SUPERUSER.runAs(scanAction);
509       d = new Delete(row1);
510       // with visibility
511       d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
512       d.addColumns(fam, qual, HConstants.LATEST_TIMESTAMP);
513       table.delete(d);
514       scanAction = new PrivilegedExceptionAction<Void>() {
515         @Override
516         public Void run() throws Exception {
517           try (Connection connection = ConnectionFactory.createConnection(conf);
518               Table table = connection.getTable(tableName)) {
519             Scan s = new Scan();
520             ResultScanner scanner = table.getScanner(s);
521             Result[] next = scanner.next(3);
522             assertEquals(next.length, 0);
523           } catch (Throwable t) {
524             throw new IOException(t);
525           }
526           return null;
527         }
528       };
529       SUPERUSER.runAs(scanAction);
530     }
531   }
532 
533   @Test
534   public void testDeleteColumnsWithAndWithoutVisibilityLabels() throws Exception {
535     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
536     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
537     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
538     HTableDescriptor desc = new HTableDescriptor(tableName);
539     desc.addFamily(colDesc);
540     hBaseAdmin.createTable(desc);
541     try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
542       Put put = new Put(row1);
543       put.addColumn(fam, qual, value);
544       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
545       table.put(put);
546       Delete d = new Delete(row1);
547       // with visibility
548       d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
549       d.addColumns(fam, qual, HConstants.LATEST_TIMESTAMP);
550       table.delete(d);
551       PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
552         @Override
553         public Void run() throws Exception {
554           try (Connection connection = ConnectionFactory.createConnection(conf);
555               Table table = connection.getTable(tableName)) {
556             Scan s = new Scan();
557             ResultScanner scanner = table.getScanner(s);
558             Result[] next = scanner.next(3);
559             assertEquals(next.length, 0);
560           } catch (Throwable t) {
561             throw new IOException(t);
562           }
563           return null;
564         }
565       };
566       SUPERUSER.runAs(scanAction);
567       d = new Delete(row1);
568       // without visibility
569       d.addColumns(fam, qual, HConstants.LATEST_TIMESTAMP);
570       table.delete(d);
571       scanAction = new PrivilegedExceptionAction<Void>() {
572         @Override
573         public Void run() throws Exception {
574           try (Connection connection = ConnectionFactory.createConnection(conf);
575               Table table = connection.getTable(tableName)) {
576             Scan s = new Scan();
577             ResultScanner scanner = table.getScanner(s);
578             Result[] next = scanner.next(3);
579             assertEquals(next.length, 0);
580           } catch (Throwable t) {
581             throw new IOException(t);
582           }
583           return null;
584         }
585       };
586       SUPERUSER.runAs(scanAction);
587     }
588   }
589 
590   @Test
591   public void testDeleteFamiliesWithoutAndWithVisibilityLabels() throws Exception {
592     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
593     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
594     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
595     HTableDescriptor desc = new HTableDescriptor(tableName);
596     desc.addFamily(colDesc);
597     hBaseAdmin.createTable(desc);
598     try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
599       Put put = new Put(row1);
600       put.addColumn(fam, qual, value);
601       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
602       table.put(put);
603       Delete d = new Delete(row1);
604       // without visibility
605       d.addFamily(fam);
606       table.delete(d);
607       PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
608         @Override
609         public Void run() throws Exception {
610           try (Connection connection = ConnectionFactory.createConnection(conf);
611               Table table = connection.getTable(tableName)) {
612             Scan s = new Scan();
613             ResultScanner scanner = table.getScanner(s);
614             Result[] next = scanner.next(3);
615             assertEquals(next.length, 1);
616           } catch (Throwable t) {
617             throw new IOException(t);
618           }
619           return null;
620         }
621       };
622       SUPERUSER.runAs(scanAction);
623       d = new Delete(row1);
624       // with visibility
625       d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
626       d.addFamily(fam);
627       table.delete(d);
628       scanAction = new PrivilegedExceptionAction<Void>() {
629         @Override
630         public Void run() throws Exception {
631           try (Connection connection = ConnectionFactory.createConnection(conf);
632               Table table = connection.getTable(tableName)) {
633             Scan s = new Scan();
634             ResultScanner scanner = table.getScanner(s);
635             Result[] next = scanner.next(3);
636             assertEquals(next.length, 0);
637           } catch (Throwable t) {
638             throw new IOException(t);
639           }
640           return null;
641         }
642       };
643       SUPERUSER.runAs(scanAction);
644     }
645   }
646 
647   @Test
648   public void testDeleteFamiliesWithAndWithoutVisibilityLabels() throws Exception {
649     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
650     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
651     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
652     HTableDescriptor desc = new HTableDescriptor(tableName);
653     desc.addFamily(colDesc);
654     hBaseAdmin.createTable(desc);
655     try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
656       Put put = new Put(row1);
657       put.addColumn(fam, qual, value);
658       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
659       table.put(put);
660       Delete d = new Delete(row1);
661       d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
662       // with visibility
663       d.addFamily(fam);
664       table.delete(d);
665       PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
666         @Override
667         public Void run() throws Exception {
668           try (Connection connection = ConnectionFactory.createConnection(conf);
669               Table table = connection.getTable(tableName)) {
670             Scan s = new Scan();
671             ResultScanner scanner = table.getScanner(s);
672             Result[] next = scanner.next(3);
673             assertEquals(next.length, 0);
674           } catch (Throwable t) {
675             throw new IOException(t);
676           }
677           return null;
678         }
679       };
680       SUPERUSER.runAs(scanAction);
681       d = new Delete(row1);
682       // without visibility
683       d.addFamily(fam);
684       table.delete(d);
685       scanAction = new PrivilegedExceptionAction<Void>() {
686         @Override
687         public Void run() throws Exception {
688           try (Connection connection = ConnectionFactory.createConnection(conf);
689               Table table = connection.getTable(tableName)) {
690             Scan s = new Scan();
691             ResultScanner scanner = table.getScanner(s);
692             Result[] next = scanner.next(3);
693             assertEquals(next.length, 0);
694           } catch (Throwable t) {
695             throw new IOException(t);
696           }
697           return null;
698         }
699       };
700       SUPERUSER.runAs(scanAction);
701     }
702   }
703 
704   @Test
705   public void testDeletesWithoutAndWithVisibilityLabels() throws Exception {
706     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
707     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
708     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
709     HTableDescriptor desc = new HTableDescriptor(tableName);
710     desc.addFamily(colDesc);
711     hBaseAdmin.createTable(desc);
712     try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
713       Put put = new Put(row1);
714       put.addColumn(fam, qual, value);
715       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
716       table.put(put);
717       Delete d = new Delete(row1);
718       // without visibility
719       d.addColumn(fam, qual);
720       table.delete(d);
721       PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
722         @Override
723         public Void run() throws Exception {
724           try (Connection connection = ConnectionFactory.createConnection(conf);
725               Table table = connection.getTable(tableName)) {
726             Scan s = new Scan();
727             ResultScanner scanner = table.getScanner(s);
728             // The delete would not be able to apply it because of visibility mismatch
729             Result[] next = scanner.next(3);
730             assertEquals(next.length, 1);
731           } catch (Throwable t) {
732             throw new IOException(t);
733           }
734           return null;
735         }
736       };
737       SUPERUSER.runAs(scanAction);
738       d = new Delete(row1);
739       // with visibility
740       d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
741       d.addColumn(fam, qual);
742       table.delete(d);
743       scanAction = new PrivilegedExceptionAction<Void>() {
744         @Override
745         public Void run() throws Exception {
746           try (Connection connection = ConnectionFactory.createConnection(conf);
747               Table table = connection.getTable(tableName)) {
748             Scan s = new Scan();
749             ResultScanner scanner = table.getScanner(s);
750             Result[] next = scanner.next(3);
751             // this will alone match
752             assertEquals(next.length, 0);
753           } catch (Throwable t) {
754             throw new IOException(t);
755           }
756           return null;
757         }
758       };
759       SUPERUSER.runAs(scanAction);
760     }
761   }
762 
763   @Test
764   public void testVisibilityLabelsWithDeleteFamilyWithPutsReAppearing() throws Exception {
765     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
766     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
767     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
768     colDesc.setMaxVersions(5);
769     HTableDescriptor desc = new HTableDescriptor(tableName);
770     desc.addFamily(colDesc);
771     hBaseAdmin.createTable(desc);
772     try (Table table = new HTable(conf, tableName)) {
773       Put put = new Put(Bytes.toBytes("row1"));
774       put.add(fam, qual, value);
775       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
776       table.put(put);
777       put = new Put(Bytes.toBytes("row1"));
778       put.add(fam, qual, value);
779       put.setCellVisibility(new CellVisibility(SECRET));
780       table.put(put);
781       TEST_UTIL.getHBaseAdmin().flush(tableName);
782       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
783         @Override
784         public Void run() throws Exception {
785           try (Connection connection = ConnectionFactory.createConnection(conf);
786                Table table = connection.getTable(tableName)) {
787             Delete d = new Delete(row1);
788             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
789             d.addFamily(fam);
790             table.delete(d);
791           } catch (Throwable t) {
792             throw new IOException(t);
793           }
794           return null;
795         }
796       };
797       SUPERUSER.runAs(actiona);
798       Scan s = new Scan();
799       s.setMaxVersions(5);
800       s.setAuthorizations(new Authorizations(SECRET));
801       ResultScanner scanner = table.getScanner(s);
802       Result[] next = scanner.next(3);
803       assertEquals(next.length, 1);
804       put = new Put(Bytes.toBytes("row1"));
805       put.add(fam, qual, value1);
806       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
807       table.put(put);
808       actiona = new PrivilegedExceptionAction<Void>() {
809         @Override
810         public Void run() throws Exception {
811           try (Connection connection = ConnectionFactory.createConnection(conf);
812                Table table = connection.getTable(tableName)) {
813             Delete d = new Delete(row1);
814             d.setCellVisibility(new CellVisibility(SECRET));
815             d.addFamily(fam);
816             table.delete(d);
817           } catch (Throwable t) {
818             throw new IOException(t);
819           }
820           return null;
821         }
822       };
823       SUPERUSER.runAs(actiona);
824       s = new Scan();
825       s.setMaxVersions(5);
826       s.setAuthorizations(new Authorizations(CONFIDENTIAL));
827       scanner = table.getScanner(s);
828       next = scanner.next(3);
829       assertEquals(next.length, 1);
830       s = new Scan();
831       s.setMaxVersions(5);
832       s.setAuthorizations(new Authorizations(SECRET));
833       scanner = table.getScanner(s);
834       Result[] next1 = scanner.next(3);
835       assertEquals(next1.length, 0);
836     }
837   }
838 
839   @Test
840   public void testVisibilityLabelsWithDeleteColumnsWithPutsReAppearing() throws Exception {
841     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
842     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
843     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
844     colDesc.setMaxVersions(5);
845     HTableDescriptor desc = new HTableDescriptor(tableName);
846     desc.addFamily(colDesc);
847     hBaseAdmin.createTable(desc);
848     try (Table table = new HTable(conf, tableName)) {
849       Put put = new Put(Bytes.toBytes("row1"));
850       put.add(fam, qual, value);
851       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
852       table.put(put);
853       put = new Put(Bytes.toBytes("row1"));
854       put.add(fam, qual, value);
855       put.setCellVisibility(new CellVisibility(SECRET));
856       table.put(put);
857       TEST_UTIL.getHBaseAdmin().flush(tableName);
858       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
859         @Override
860         public Void run() throws Exception {
861           try (Connection connection = ConnectionFactory.createConnection(conf);
862                Table table = connection.getTable(tableName)) {
863             Delete d = new Delete(row1);
864             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
865             d.addColumns(fam, qual);
866             table.delete(d);
867           } catch (Throwable t) {
868             throw new IOException(t);
869           }
870           return null;
871         }
872       };
873       SUPERUSER.runAs(actiona);
874       Scan s = new Scan();
875       s.setMaxVersions(5);
876       s.setAuthorizations(new Authorizations(SECRET));
877       ResultScanner scanner = table.getScanner(s);
878       Result[] next = scanner.next(3);
879       assertEquals(next.length, 1);
880       put = new Put(Bytes.toBytes("row1"));
881       put.add(fam, qual, value1);
882       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
883       table.put(put);
884       actiona = new PrivilegedExceptionAction<Void>() {
885         @Override
886         public Void run() throws Exception {
887           try (Connection connection = ConnectionFactory.createConnection(conf);
888                Table table = connection.getTable(tableName)) {
889             Delete d = new Delete(row1);
890             d.setCellVisibility(new CellVisibility(SECRET));
891             d.addColumns(fam, qual);
892             table.delete(d);
893           } catch (Throwable t) {
894             throw new IOException(t);
895           }
896           return null;
897         }
898       };
899       SUPERUSER.runAs(actiona);
900       s = new Scan();
901       s.setMaxVersions(5);
902       s.setAuthorizations(new Authorizations(CONFIDENTIAL));
903       scanner = table.getScanner(s);
904       next = scanner.next(3);
905       assertEquals(next.length, 1);
906       s = new Scan();
907       s.setMaxVersions(5);
908       s.setAuthorizations(new Authorizations(SECRET));
909       scanner = table.getScanner(s);
910       Result[] next1 = scanner.next(3);
911       assertEquals(next1.length, 0);
912     }
913   }
914 
915   @Test
916   public void testVisibilityCombinations() throws Exception {
917     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
918     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
919     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
920     colDesc.setMaxVersions(5);
921     HTableDescriptor desc = new HTableDescriptor(tableName);
922     desc.addFamily(colDesc);
923     hBaseAdmin.createTable(desc);
924     try (Table table = new HTable(conf, tableName)) {
925       Put put = new Put(Bytes.toBytes("row1"));
926       put.add(fam, qual, 123l, value);
927       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
928       table.put(put);
929       put = new Put(Bytes.toBytes("row1"));
930       put.add(fam, qual, 124l, value1);
931       put.setCellVisibility(new CellVisibility(SECRET));
932       table.put(put);
933       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
934         @Override
935         public Void run() throws Exception {
936           try (Connection connection = ConnectionFactory.createConnection(conf);
937                Table table = connection.getTable(tableName)) {
938             Delete d = new Delete(row1);
939             d.setCellVisibility(new CellVisibility(SECRET));
940             d.addColumns(fam, qual, 126l);
941             table.delete(d);
942           } catch (Throwable t) {
943             throw new IOException(t);
944           }
945 
946           try (Connection connection = ConnectionFactory.createConnection(conf);
947                Table table = connection.getTable(tableName)) {
948             Delete d = new Delete(row1);
949             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
950             d.addColumn(fam, qual, 123l);
951             table.delete(d);
952           } catch (Throwable t) {
953             throw new IOException(t);
954           }
955           return null;
956         }
957       };
958       SUPERUSER.runAs(actiona);
959       Scan s = new Scan();
960       s.setMaxVersions(5);
961       s.setAuthorizations(new Authorizations(CONFIDENTIAL, SECRET));
962       ResultScanner scanner = table.getScanner(s);
963       Result[] next = scanner.next(3);
964       assertEquals(next.length, 0);
965     }
966   }
967   @Test
968   public void testVisibilityLabelsWithDeleteColumnWithSpecificVersionWithPutsReAppearing()
969       throws Exception {
970     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
971     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
972     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
973     colDesc.setMaxVersions(5);
974     HTableDescriptor desc = new HTableDescriptor(tableName);
975     desc.addFamily(colDesc);
976     hBaseAdmin.createTable(desc);
977 
978     try (Table table = new HTable(conf, tableName)) {
979       Put put1 = new Put(Bytes.toBytes("row1"));
980       put1.add(fam, qual, 123l, value);
981       put1.setCellVisibility(new CellVisibility(CONFIDENTIAL));
982 
983       Put put2 = new Put(Bytes.toBytes("row1"));
984       put2.add(fam, qual, 123l, value1);
985       put2.setCellVisibility(new CellVisibility(SECRET));
986       table.put(createList(put1, put2));
987 
988       Scan s = new Scan();
989       s.setMaxVersions(5);
990       s.setAuthorizations(new Authorizations(CONFIDENTIAL, SECRET));
991 
992       ResultScanner scanner = table.getScanner(s);
993       assertEquals(scanner.next(3).length, 1);
994       scanner.close();
995 
996       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
997         @Override
998         public Void run() throws Exception {
999           try (Connection connection = ConnectionFactory.createConnection(conf);
1000                Table table = connection.getTable(tableName)) {
1001             Delete d = new Delete(row1);
1002             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1003             d.addColumn(fam, qual, 123l);
1004             table.delete(d);
1005           }
1006 
1007           try (Connection connection = ConnectionFactory.createConnection(conf);
1008                Table table = connection.getTable(tableName)) {
1009             Delete d = new Delete(row1);
1010             d.setCellVisibility(new CellVisibility(SECRET));
1011             d.addColumn(fam, qual, 123l);
1012             table.delete(d);
1013           } catch (Throwable t) {
1014             throw new IOException(t);
1015           }
1016           return null;
1017         }
1018       };
1019       SUPERUSER.runAs(actiona);
1020       s = new Scan();
1021       s.setMaxVersions(5);
1022       s.setAuthorizations(new Authorizations(CONFIDENTIAL));
1023       scanner = table.getScanner(s);
1024       assertEquals(scanner.next(3).length, 0);
1025       scanner.close();
1026     }
1027   }
1028 
1029   @Test
1030   public void
1031     testVisibilityLabelsWithDeleteFamilyWithNoMatchingVisExpWithMultipleVersionsNoTimestamp()
1032       throws Exception {
1033     setAuths();
1034     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1035     try (Table table = doPuts(tableName)) {
1036       TEST_UTIL.getHBaseAdmin().flush(tableName);
1037       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1038         @Override
1039         public Void run() throws Exception {
1040           Delete d1 = new Delete(row1);
1041           d1.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1042           d1.addFamily(fam);
1043 
1044           Delete d2 = new Delete(row1);
1045           d2.setCellVisibility(new CellVisibility(SECRET));
1046           d2.addFamily(fam);
1047 
1048           Delete d3 = new Delete(row1);
1049           d3.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
1050               + SECRET + "&" + TOPSECRET + ")"));
1051           d3.addFamily(fam);
1052 
1053           try (Connection connection = ConnectionFactory.createConnection(conf);
1054                Table table = connection.getTable(tableName)) {
1055             table.delete(createList(d1, d2, d3));
1056           } catch (Throwable t) {
1057             throw new IOException(t);
1058           }
1059           return null;
1060         }
1061       };
1062       SUPERUSER.runAs(actiona);
1063       Scan s = new Scan();
1064       s.setMaxVersions(5);
1065       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1066       ResultScanner scanner = table.getScanner(s);
1067       Result[] next = scanner.next(3);
1068       assertTrue(next.length == 2);
1069       CellScanner cellScanner = next[0].cellScanner();
1070       cellScanner.advance();
1071       Cell current = cellScanner.current();
1072       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1073           current.getRowLength(), row1, 0, row1.length));
1074       cellScanner = next[1].cellScanner();
1075       cellScanner.advance();
1076       current = cellScanner.current();
1077       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1078           current.getRowLength(), row2, 0, row2.length));
1079       scanner.close();
1080     }
1081   }
1082 
1083   @Test
1084   public void testDeleteFamilyAndDeleteColumnsWithAndWithoutVisibilityExp() throws Exception {
1085     setAuths();
1086     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1087     try (Table table = doPuts(tableName)) {
1088       TEST_UTIL.getHBaseAdmin().flush(tableName);
1089       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1090         @Override
1091         public Void run() throws Exception {
1092           Delete d1 = new Delete(row1);
1093           d1.addFamily(fam);
1094 
1095           Delete d2 = new Delete(row1);
1096           d2.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1097           d2.addColumns(fam, qual);
1098           try (Connection connection = ConnectionFactory.createConnection(conf);
1099                Table table = connection.getTable(tableName)) {
1100             table.delete(createList(d1, d2));
1101           } catch (Throwable t) {
1102             throw new IOException(t);
1103           }
1104           return null;
1105         }
1106       };
1107       SUPERUSER.runAs(actiona);
1108       Scan s = new Scan();
1109       s.setMaxVersions(5);
1110       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1111       ResultScanner scanner = table.getScanner(s);
1112       Result[] next = scanner.next(3);
1113       assertTrue(next.length == 2);
1114       CellScanner cellScanner = next[0].cellScanner();
1115       cellScanner.advance();
1116       Cell current = cellScanner.current();
1117       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1118           current.getRowLength(), row1, 0, row1.length));
1119       assertEquals(current.getTimestamp(), 127l);
1120       cellScanner.advance();
1121       current = cellScanner.current();
1122       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1123           current.getRowLength(), row1, 0, row1.length));
1124       assertEquals(current.getTimestamp(), 126l);
1125       cellScanner.advance();
1126       current = cellScanner.current();
1127       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1128           current.getRowLength(), row1, 0, row1.length));
1129       assertEquals(current.getTimestamp(), 124l);
1130       cellScanner.advance();
1131       current = cellScanner.current();
1132       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1133           current.getRowLength(), row1, 0, row1.length));
1134       assertEquals(current.getTimestamp(), 123l);
1135       cellScanner = next[1].cellScanner();
1136       cellScanner.advance();
1137       current = cellScanner.current();
1138       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1139           current.getRowLength(), row2, 0, row2.length));
1140       scanner.close();
1141     }
1142   }
1143 
1144   private Table doPuts(TableName tableName) throws IOException, InterruptedIOException,
1145       RetriesExhaustedWithDetailsException, InterruptedException {
1146     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
1147     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
1148     colDesc.setMaxVersions(5);
1149     HTableDescriptor desc = new HTableDescriptor(tableName);
1150     desc.addFamily(colDesc);
1151     hBaseAdmin.createTable(desc);
1152 
1153     List<Put> puts = new ArrayList<Put>();
1154     Put put = new Put(Bytes.toBytes("row1"));
1155     put.add(fam, qual, 123l, value);
1156     put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1157     puts.add(put);
1158 
1159     put = new Put(Bytes.toBytes("row1"));
1160     put.add(fam, qual, 124l, value);
1161     put.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
1162     + TOPSECRET + "&" + SECRET+")"));
1163     puts.add(put);
1164 
1165     put = new Put(Bytes.toBytes("row1"));
1166     put.add(fam, qual, 125l, value);
1167     put.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1168     puts.add(put);
1169 
1170     put = new Put(Bytes.toBytes("row1"));
1171     put.add(fam, qual, 126l, value);
1172     put.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
1173         + TOPSECRET + "&" + SECRET+")"));
1174     puts.add(put);
1175 
1176     put = new Put(Bytes.toBytes("row1"));
1177     put.add(fam, qual, 127l, value);
1178     put.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
1179         + TOPSECRET + "&" + SECRET+")"));
1180     puts.add(put);
1181 
1182     TEST_UTIL.getHBaseAdmin().flush(tableName);
1183     put = new Put(Bytes.toBytes("row2"));
1184     put.add(fam, qual, 127l, value);
1185     put.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|(" + TOPSECRET
1186         + "&" + SECRET + ")"));
1187     puts.add(put);
1188 
1189     Table table = new HTable(conf, tableName);
1190     table.put(puts);
1191     return table;
1192   }
1193 
1194   private Table doPutsWithDiffCols(TableName tableName) throws IOException,
1195       InterruptedIOException, RetriesExhaustedWithDetailsException, InterruptedException {
1196     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
1197     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
1198     colDesc.setMaxVersions(5);
1199     HTableDescriptor desc = new HTableDescriptor(tableName);
1200     desc.addFamily(colDesc);
1201     hBaseAdmin.createTable(desc);
1202 
1203     List<Put> puts = new ArrayList<>();
1204     Put put = new Put(Bytes.toBytes("row1"));
1205     put.add(fam, qual, 123l, value);
1206     put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1207     puts.add(put);
1208 
1209     put = new Put(Bytes.toBytes("row1"));
1210     put.add(fam, qual, 124l, value);
1211     put.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
1212     + TOPSECRET + "&" + SECRET+")"));
1213     puts.add(put);
1214 
1215     put = new Put(Bytes.toBytes("row1"));
1216     put.add(fam, qual, 125l, value);
1217     put.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1218     puts.add(put);
1219 
1220     put = new Put(Bytes.toBytes("row1"));
1221     put.add(fam, qual1, 126l, value);
1222     put.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1223     puts.add(put);
1224 
1225     put = new Put(Bytes.toBytes("row1"));
1226     put.add(fam, qual2, 127l, value);
1227     put.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
1228         + TOPSECRET + "&" + SECRET+")"));
1229     puts.add(put);
1230 
1231     Table table = new HTable(conf, tableName);
1232     table.put(puts);
1233     return table;
1234   }
1235 
1236   private Table doPutsWithoutVisibility(TableName tableName) throws IOException,
1237       InterruptedIOException, RetriesExhaustedWithDetailsException, InterruptedException {
1238     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
1239     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
1240     colDesc.setMaxVersions(5);
1241     HTableDescriptor desc = new HTableDescriptor(tableName);
1242     desc.addFamily(colDesc);
1243     hBaseAdmin.createTable(desc);
1244     List<Put> puts = new ArrayList<>();
1245     Put put = new Put(Bytes.toBytes("row1"));
1246     put.add(fam, qual, 123l, value);
1247     puts.add(put);
1248 
1249     put = new Put(Bytes.toBytes("row1"));
1250     put.add(fam, qual, 124l, value);
1251     puts.add(put);
1252 
1253     put = new Put(Bytes.toBytes("row1"));
1254     put.add(fam, qual, 125l, value);
1255     puts.add(put);
1256 
1257     put = new Put(Bytes.toBytes("row1"));
1258     put.add(fam, qual, 126l, value);
1259     puts.add(put);
1260 
1261     put = new Put(Bytes.toBytes("row1"));
1262     put.add(fam, qual, 127l, value);
1263     puts.add(put);
1264 
1265     Table table = new HTable(conf, tableName);
1266     table.put(puts);
1267 
1268     TEST_UTIL.getHBaseAdmin().flush(tableName);
1269 
1270     put = new Put(Bytes.toBytes("row2"));
1271     put.add(fam, qual, 127l, value);
1272     table.put(put);
1273 
1274     return table;
1275   }
1276 
1277 
1278   @Test
1279   public void testDeleteColumnWithSpecificTimeStampUsingMultipleVersionsUnMatchingVisExpression()
1280       throws Exception {
1281     setAuths();
1282     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1283     try (Table table = doPuts(tableName)) {
1284       TEST_UTIL.getHBaseAdmin().flush(tableName);
1285       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1286         @Override
1287         public Void run() throws Exception {
1288           try (Connection connection = ConnectionFactory.createConnection(conf);
1289                Table table = connection.getTable(tableName)) {
1290             Delete d = new Delete(row1);
1291             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|(" +
1292                 SECRET + "&" + TOPSECRET+")"));
1293             d.addColumn(fam, qual, 125l);
1294             table.delete(d);
1295           } catch (Throwable t) {
1296             throw new IOException(t);
1297           }
1298           return null;
1299         }
1300       };
1301       SUPERUSER.runAs(actiona);
1302 
1303       TEST_UTIL.getHBaseAdmin().flush(tableName);
1304       Scan s = new Scan();
1305       s.setMaxVersions(5);
1306       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1307       ResultScanner scanner = table.getScanner(s);
1308       Result[] next = scanner.next(3);
1309       assertTrue(next.length == 2);
1310       CellScanner cellScanner = next[0].cellScanner();
1311       cellScanner.advance();
1312       Cell current = cellScanner.current();
1313       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1314           current.getRowLength(), row1, 0, row1.length));
1315       assertEquals(current.getTimestamp(), 127l);
1316       cellScanner.advance();
1317       current = cellScanner.current();
1318       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1319           current.getRowLength(), row1, 0, row1.length));
1320       assertEquals(current.getTimestamp(), 126l);
1321       cellScanner.advance();
1322       current = cellScanner.current();
1323       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1324           current.getRowLength(), row1, 0, row1.length));
1325       assertEquals(current.getTimestamp(), 125l);
1326       cellScanner.advance();
1327       current = cellScanner.current();
1328       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1329           current.getRowLength(), row1, 0, row1.length));
1330       assertEquals(current.getTimestamp(), 124l);
1331       cellScanner.advance();
1332       current = cellScanner.current();
1333       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1334           current.getRowLength(), row1, 0, row1.length));
1335       assertEquals(current.getTimestamp(), 123l);
1336       cellScanner = next[1].cellScanner();
1337       cellScanner.advance();
1338       current = cellScanner.current();
1339       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1340           current.getRowLength(), row2, 0, row2.length));
1341     }
1342   }
1343 
1344   @Test
1345   public void testDeleteColumnWithLatestTimeStampUsingMultipleVersions() throws Exception {
1346     setAuths();
1347     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1348     try (Table table = doPuts(tableName)) {
1349       TEST_UTIL.getHBaseAdmin().flush(tableName);
1350       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1351         @Override
1352         public Void run() throws Exception {
1353           try (Connection connection = ConnectionFactory.createConnection(conf);
1354                Table table = connection.getTable(tableName)) {
1355             Delete d = new Delete(row1);
1356             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1357             d.addColumn(fam, qual);
1358             table.delete(d);
1359           } catch (Throwable t) {
1360             throw new IOException(t);
1361           }
1362           return null;
1363         }
1364       };
1365       SUPERUSER.runAs(actiona);
1366 
1367       TEST_UTIL.getHBaseAdmin().flush(tableName);
1368       Scan s = new Scan();
1369       s.setMaxVersions(5);
1370       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1371       ResultScanner scanner = table.getScanner(s);
1372       Result[] next = scanner.next(3);
1373       assertTrue(next.length == 2);
1374       CellScanner cellScanner = next[0].cellScanner();
1375       cellScanner.advance();
1376       Cell current = cellScanner.current();
1377       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1378           current.getRowLength(), row1, 0, row1.length));
1379       assertEquals(current.getTimestamp(), 127l);
1380       cellScanner.advance();
1381       current = cellScanner.current();
1382       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1383           current.getRowLength(), row1, 0, row1.length));
1384       assertEquals(current.getTimestamp(), 126l);
1385       cellScanner.advance();
1386       current = cellScanner.current();
1387       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1388           current.getRowLength(), row1, 0, row1.length));
1389       assertEquals(current.getTimestamp(), 124l);
1390       cellScanner.advance();
1391       current = cellScanner.current();
1392       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1393           current.getRowLength(), row1, 0, row1.length));
1394       assertEquals(current.getTimestamp(), 123l);
1395       cellScanner = next[1].cellScanner();
1396       cellScanner.advance();
1397       current = cellScanner.current();
1398       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1399           current.getRowLength(), row2, 0, row2.length));
1400     }
1401   }
1402 
1403   @Test (timeout=180000)
1404   public void testDeleteColumnWithLatestTimeStampWhenNoVersionMatches() throws Exception {
1405     setAuths();
1406     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1407     try (Table table = doPuts(tableName)) {
1408       TEST_UTIL.getHBaseAdmin().flush(tableName);
1409       Put put = new Put(Bytes.toBytes("row1"));
1410       put.add(fam, qual, 128l, value);
1411       put.setCellVisibility(new CellVisibility(TOPSECRET));
1412       table.put(put);
1413       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1414         @Override
1415         public Void run() throws Exception {
1416           try (Connection connection = ConnectionFactory.createConnection(conf);
1417                Table table = connection.getTable(tableName)) {
1418             Delete d = new Delete(row1);
1419             d.setCellVisibility(new CellVisibility(SECRET ));
1420             d.addColumn(fam, qual);
1421             table.delete(d);
1422           } catch (Throwable t) {
1423             throw new IOException(t);
1424           }
1425           return null;
1426         }
1427       };
1428       SUPERUSER.runAs(actiona);
1429 
1430       TEST_UTIL.getHBaseAdmin().flush(tableName);
1431       Scan s = new Scan();
1432       s.setMaxVersions(5);
1433       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1434       ResultScanner scanner = table.getScanner(s);
1435       Result[] next = scanner.next(3);
1436       assertTrue(next.length == 2);
1437       CellScanner cellScanner = next[0].cellScanner();
1438       cellScanner.advance();
1439       Cell current = cellScanner.current();
1440       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1441           current.getRowLength(), row1, 0, row1.length));
1442       assertEquals(current.getTimestamp(), 128l);
1443       cellScanner.advance();
1444       current = cellScanner.current();
1445       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1446           current.getRowLength(), row1, 0, row1.length));
1447       assertEquals(current.getTimestamp(), 127l);
1448       cellScanner.advance();
1449       current = cellScanner.current();
1450       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1451           current.getRowLength(), row1, 0, row1.length));
1452       assertEquals(current.getTimestamp(), 126l);
1453       cellScanner.advance();
1454       current = cellScanner.current();
1455       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1456           current.getRowLength(), row1, 0, row1.length));
1457       assertEquals(current.getTimestamp(), 125l);
1458       cellScanner.advance();
1459       current = cellScanner.current();
1460       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1461           current.getRowLength(), row1, 0, row1.length));
1462       assertEquals(current.getTimestamp(), 124l);
1463       cellScanner = next[1].cellScanner();
1464       cellScanner.advance();
1465       current = cellScanner.current();
1466       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1467           current.getRowLength(), row2, 0, row2.length));
1468 
1469       put = new Put(Bytes.toBytes("row1"));
1470       put.add(fam, qual, 129l, value);
1471       put.setCellVisibility(new CellVisibility(SECRET));
1472       table.put(put);
1473 
1474       TEST_UTIL.getHBaseAdmin().flush(tableName);
1475       s = new Scan();
1476       s.setMaxVersions(5);
1477       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1478       scanner = table.getScanner(s);
1479       next = scanner.next(3);
1480       assertTrue(next.length == 2);
1481       cellScanner = next[0].cellScanner();
1482       cellScanner.advance();
1483       current = cellScanner.current();
1484       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1485           current.getRowLength(), row1, 0, row1.length));
1486       assertEquals(current.getTimestamp(), 129l);
1487     }
1488   }
1489   @Test
1490   public void testDeleteColumnWithLatestTimeStampUsingMultipleVersionsAfterCompaction()
1491       throws Exception {
1492     setAuths();
1493     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1494     try (Table table = doPuts(tableName)) {
1495       TEST_UTIL.getHBaseAdmin().flush(tableName);
1496       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1497         @Override
1498         public Void run() throws Exception {
1499           try (Connection connection = ConnectionFactory.createConnection(conf);
1500                Table table = connection.getTable(tableName)) {
1501             Delete d = new Delete(row1);
1502             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1503             d.addColumn(fam, qual);
1504             table.delete(d);
1505           } catch (Throwable t) {
1506             throw new IOException(t);
1507           }
1508           return null;
1509         }
1510       };
1511       SUPERUSER.runAs(actiona);
1512       TEST_UTIL.getHBaseAdmin().flush(tableName);
1513       Put put = new Put(Bytes.toBytes("row3"));
1514       put.add(fam, qual, 127l, value);
1515       put.setCellVisibility(new CellVisibility(CONFIDENTIAL + "&" + PRIVATE));
1516       table.put(put);
1517       TEST_UTIL.getHBaseAdmin().flush(tableName);
1518       TEST_UTIL.getHBaseAdmin().majorCompact(tableName);
1519       // Sleep to ensure compaction happens. Need to do it in a better way
1520       Thread.sleep(5000);
1521       Scan s = new Scan();
1522       s.setMaxVersions(5);
1523       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1524       ResultScanner scanner = table.getScanner(s);
1525       Result[] next = scanner.next(3);
1526       assertTrue(next.length == 3);
1527       CellScanner cellScanner = next[0].cellScanner();
1528       cellScanner.advance();
1529       Cell current = cellScanner.current();
1530       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1531           current.getRowLength(), row1, 0, row1.length));
1532       assertEquals(current.getTimestamp(), 127l);
1533       cellScanner.advance();
1534       current = cellScanner.current();
1535       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1536           current.getRowLength(), row1, 0, row1.length));
1537       assertEquals(current.getTimestamp(), 126l);
1538       cellScanner.advance();
1539       current = cellScanner.current();
1540       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1541           current.getRowLength(), row1, 0, row1.length));
1542       assertEquals(current.getTimestamp(), 124l);
1543       cellScanner.advance();
1544       current = cellScanner.current();
1545       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1546           current.getRowLength(), row1, 0, row1.length));
1547       assertEquals(current.getTimestamp(), 123l);
1548       cellScanner = next[1].cellScanner();
1549       cellScanner.advance();
1550       current = cellScanner.current();
1551       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1552           current.getRowLength(), row2, 0, row2.length));
1553     }
1554   }
1555 
1556   @Test
1557   public void testDeleteFamilyLatestTimeStampWithMulipleVersions() throws Exception {
1558     setAuths();
1559     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1560     try (Table table = doPuts(tableName)) {
1561       TEST_UTIL.getHBaseAdmin().flush(tableName);
1562       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1563         @Override
1564         public Void run() throws Exception {
1565           try (Connection connection = ConnectionFactory.createConnection(conf);
1566                Table table = connection.getTable(tableName)) {
1567             Delete d = new Delete(row1);
1568             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1569             d.addFamily(fam);
1570             table.delete(d);
1571           } catch (Throwable t) {
1572             throw new IOException(t);
1573           }
1574           return null;
1575         }
1576       };
1577       SUPERUSER.runAs(actiona);
1578 
1579       TEST_UTIL.getHBaseAdmin().flush(tableName);
1580       Scan s = new Scan();
1581       s.setMaxVersions(5);
1582       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1583       ResultScanner scanner = table.getScanner(s);
1584       Result[] next = scanner.next(3);
1585       assertTrue(next.length == 2);
1586       CellScanner cellScanner = next[0].cellScanner();
1587       cellScanner.advance();
1588       Cell current = cellScanner.current();
1589       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1590           current.getRowLength(), row1, 0, row1.length));
1591       assertEquals(current.getTimestamp(), 127l);
1592       cellScanner.advance();
1593       current = cellScanner.current();
1594       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1595           current.getRowLength(), row1, 0, row1.length));
1596       assertEquals(current.getTimestamp(), 126l);
1597       cellScanner = next[1].cellScanner();
1598       cellScanner.advance();
1599       current = cellScanner.current();
1600       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1601           current.getRowLength(), row2, 0, row2.length));
1602     }
1603   }
1604 
1605   @Test
1606   public void testDeleteColumnswithMultipleColumnsWithMultipleVersions() throws Exception {
1607     setAuths();
1608     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1609     try (Table table = doPutsWithDiffCols(tableName)) {
1610       TEST_UTIL.getHBaseAdmin().flush(tableName);
1611       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1612         @Override
1613         public Void run() throws Exception {
1614           Delete d = new Delete(row1);
1615           d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1616           d.addColumns(fam, qual, 125l);
1617           try (Connection connection = ConnectionFactory.createConnection(conf);
1618                Table table = connection.getTable(tableName)) {
1619             table.delete(d);
1620           } catch (Throwable t) {
1621             throw new IOException(t);
1622           }
1623           return null;
1624         }
1625       };
1626       SUPERUSER.runAs(actiona);
1627 
1628       TEST_UTIL.getHBaseAdmin().flush(tableName);
1629       Scan s = new Scan();
1630       s.setMaxVersions(5);
1631       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1632       ResultScanner scanner = table.getScanner(s);
1633       Result[] next = scanner.next(3);
1634       assertTrue(next.length == 1);
1635       CellScanner cellScanner = next[0].cellScanner();
1636       cellScanner.advance();
1637       Cell current = cellScanner.current();
1638       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1639           current.getRowLength(), row1, 0, row1.length));
1640       assertEquals(current.getTimestamp(), 124l);
1641       cellScanner.advance();
1642       current = cellScanner.current();
1643       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1644           current.getRowLength(), row1, 0, row1.length));
1645       assertEquals(current.getTimestamp(), 123l);
1646       cellScanner.advance();
1647       current = cellScanner.current();
1648       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1649           current.getRowLength(), row1, 0, row1.length));
1650       assertTrue(Bytes.equals(current.getQualifierArray(), current.getQualifierOffset(),
1651           current.getQualifierLength(), qual1, 0, qual1.length));
1652       assertEquals(current.getTimestamp(), 126l);
1653       cellScanner.advance();
1654       current = cellScanner.current();
1655       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1656           current.getRowLength(), row1, 0, row1.length));
1657       assertEquals(current.getTimestamp(), 127l);
1658       assertTrue(Bytes.equals(current.getQualifierArray(), current.getQualifierOffset(),
1659           current.getQualifierLength(), qual2, 0, qual2.length));
1660     }
1661   }
1662 
1663   @Test
1664   public void testDeleteColumnsWithDiffColsAndTags() throws Exception {
1665     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1666     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
1667     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
1668     colDesc.setMaxVersions(5);
1669     HTableDescriptor desc = new HTableDescriptor(tableName);
1670     desc.addFamily(colDesc);
1671     hBaseAdmin.createTable(desc);
1672     try (Table table = new HTable(conf, tableName)) {
1673       Put put = new Put(Bytes.toBytes("row1"));
1674       put.add(fam, qual1, 125l, value);
1675       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1676       table.put(put);
1677       put = new Put(Bytes.toBytes("row1"));
1678       put.add(fam, qual1, 126l, value);
1679       put.setCellVisibility(new CellVisibility(SECRET));
1680       table.put(put);
1681       TEST_UTIL.getHBaseAdmin().flush(tableName);
1682       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1683         @Override
1684         public Void run() throws Exception {
1685           Delete d1 = new Delete(row1);
1686           d1.setCellVisibility(new CellVisibility(SECRET));
1687           d1.addColumns(fam, qual, 126l);
1688 
1689           Delete d2 = new Delete(row1);
1690           d2.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1691           d2.addColumns(fam, qual1, 125l);
1692 
1693           try (Connection connection = ConnectionFactory.createConnection(conf);
1694                Table table = connection.getTable(tableName)) {
1695             table.delete(createList(d1, d2));
1696           } catch (Throwable t) {
1697             throw new IOException(t);
1698           }
1699           return null;
1700         }
1701       };
1702       SUPERUSER.runAs(actiona);
1703       Scan s = new Scan();
1704       s.setMaxVersions(5);
1705       s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
1706       ResultScanner scanner = table.getScanner(s);
1707       Result[] next = scanner.next(3);
1708       assertEquals(next.length, 1);
1709     }
1710   }
1711   @Test
1712   public void testDeleteColumnsWithDiffColsAndTags1() throws Exception {
1713     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1714     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
1715     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
1716     colDesc.setMaxVersions(5);
1717     HTableDescriptor desc = new HTableDescriptor(tableName);
1718     desc.addFamily(colDesc);
1719     hBaseAdmin.createTable(desc);
1720     try (Table table = new HTable(conf, tableName)) {
1721       Put put = new Put(Bytes.toBytes("row1"));
1722       put.add(fam, qual1, 125l, value);
1723       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1724       table.put(put);
1725       put = new Put(Bytes.toBytes("row1"));
1726       put.add(fam, qual1, 126l, value);
1727       put.setCellVisibility(new CellVisibility(SECRET));
1728       table.put(put);
1729       TEST_UTIL.getHBaseAdmin().flush(tableName);
1730       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1731         @Override
1732         public Void run() throws Exception {
1733           Delete d1 = new Delete(row1);
1734           d1.setCellVisibility(new CellVisibility(SECRET));
1735           d1.addColumns(fam, qual, 126l);
1736 
1737           Delete d2 = new Delete(row1);
1738           d2.setCellVisibility(new CellVisibility(CONFIDENTIAL));
1739           d2.addColumns(fam, qual1, 126l);
1740 
1741           try (Connection connection = ConnectionFactory.createConnection(conf);
1742                Table table = connection.getTable(tableName)) {
1743             table.delete(createList(d1, d2));
1744           } catch (Throwable t) {
1745             throw new IOException(t);
1746           }
1747           return null;
1748         }
1749       };
1750       SUPERUSER.runAs(actiona);
1751       Scan s = new Scan();
1752       s.setMaxVersions(5);
1753       s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
1754       ResultScanner scanner = table.getScanner(s);
1755       Result[] next = scanner.next(3);
1756       assertEquals(next.length, 1);
1757     }
1758   }
1759   @Test
1760   public void testDeleteFamilyWithoutCellVisibilityWithMulipleVersions() throws Exception {
1761     setAuths();
1762     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1763     try (Table table = doPutsWithoutVisibility(tableName)) {
1764       TEST_UTIL.getHBaseAdmin().flush(tableName);
1765       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1766         @Override
1767         public Void run() throws Exception {
1768           try (Connection connection = ConnectionFactory.createConnection(conf);
1769                Table table = connection.getTable(tableName)) {
1770             Delete d = new Delete(row1);
1771             d.addFamily(fam);
1772             table.delete(d);
1773           } catch (Throwable t) {
1774             throw new IOException(t);
1775           }
1776           return null;
1777         }
1778       };
1779       SUPERUSER.runAs(actiona);
1780 
1781       TEST_UTIL.getHBaseAdmin().flush(tableName);
1782       Scan s = new Scan();
1783       s.setMaxVersions(5);
1784       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1785       ResultScanner scanner = table.getScanner(s);
1786       Result[] next = scanner.next(3);
1787       assertTrue(next.length == 1);
1788       // All cells wrt row1 should be deleted as we are not passing the Cell Visibility
1789       CellScanner cellScanner = next[0].cellScanner();
1790       cellScanner.advance();
1791       Cell current = cellScanner.current();
1792       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1793           current.getRowLength(), row2, 0, row2.length));
1794     }
1795   }
1796 
1797   @Test
1798   public void testDeleteFamilyLatestTimeStampWithMulipleVersionsWithoutCellVisibilityInPuts()
1799       throws Exception {
1800     setAuths();
1801     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1802     try (Table table = doPutsWithoutVisibility(tableName)) {
1803       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1804         @Override
1805         public Void run() throws Exception {
1806           try (Connection connection = ConnectionFactory.createConnection(conf);
1807                Table table = connection.getTable(tableName)) {
1808             Delete d = new Delete(row1);
1809             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
1810             d.addFamily(fam);
1811             table.delete(d);
1812           } catch (Throwable t) {
1813             throw new IOException(t);
1814           }
1815           return null;
1816         }
1817       };
1818       SUPERUSER.runAs(actiona);
1819       TEST_UTIL.getHBaseAdmin().flush(tableName);
1820       Scan s = new Scan();
1821       s.setMaxVersions(5);
1822       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1823       ResultScanner scanner = table.getScanner(s);
1824       Result[] next = scanner.next(3);
1825       assertTrue(next.length == 2);
1826       CellScanner cellScanner = next[0].cellScanner();
1827       cellScanner.advance();
1828       Cell current = cellScanner.current();
1829       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1830           current.getRowLength(), row1, 0, row1.length));
1831       assertEquals(current.getTimestamp(), 127l);
1832       cellScanner.advance();
1833       current = cellScanner.current();
1834       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1835           current.getRowLength(), row1, 0, row1.length));
1836       assertEquals(current.getTimestamp(), 126l);
1837       cellScanner.advance();
1838       current = cellScanner.current();
1839       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1840           current.getRowLength(), row1, 0, row1.length));
1841       assertEquals(current.getTimestamp(), 125l);
1842       cellScanner.advance();
1843       current = cellScanner.current();
1844       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1845           current.getRowLength(), row1, 0, row1.length));
1846       assertEquals(current.getTimestamp(), 124l);
1847       cellScanner.advance();
1848       current = cellScanner.current();
1849       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1850           current.getRowLength(), row1, 0, row1.length));
1851       assertEquals(current.getTimestamp(), 123l);
1852       cellScanner = next[1].cellScanner();
1853       cellScanner.advance();
1854       current = cellScanner.current();
1855       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1856           current.getRowLength(), row2, 0, row2.length));
1857     }
1858   }
1859 
1860   @Test
1861   public void testDeleteFamilySpecificTimeStampWithMulipleVersions() throws Exception {
1862     setAuths();
1863     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1864     try (Table table = doPuts(tableName)) {
1865       TEST_UTIL.getHBaseAdmin().flush(tableName);
1866       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1867         @Override
1868         public Void run() throws Exception {
1869           try (Connection connection = ConnectionFactory.createConnection(conf);
1870                Table table = connection.getTable(tableName)) {
1871             Delete d = new Delete(row1);
1872             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
1873                 + SECRET + "&" + TOPSECRET + ")"));
1874             d.addFamily(fam, 126l);
1875             table.delete(d);
1876           } catch (Throwable t) {
1877             throw new IOException(t);
1878           }
1879           return null;
1880         }
1881       };
1882       SUPERUSER.runAs(actiona);
1883 
1884       TEST_UTIL.getHBaseAdmin().flush(tableName);
1885       Scan s = new Scan();
1886       s.setMaxVersions(5);
1887       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1888       ResultScanner scanner = table.getScanner(s);
1889       Result[] next = scanner.next(6);
1890       assertTrue(next.length == 2);
1891       CellScanner cellScanner = next[0].cellScanner();
1892       cellScanner.advance();
1893       Cell current = cellScanner.current();
1894       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1895           current.getRowLength(), row1, 0, row1.length));
1896       assertEquals(current.getTimestamp(), 127l);
1897       cellScanner.advance();
1898       current = cellScanner.current();
1899       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1900           current.getRowLength(), row1, 0, row1.length));
1901       assertEquals(current.getTimestamp(), 125l);
1902       cellScanner.advance();
1903       current = cellScanner.current();
1904       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1905           current.getRowLength(), row1, 0, row1.length));
1906       assertEquals(current.getTimestamp(), 123l);
1907       cellScanner = next[1].cellScanner();
1908       cellScanner.advance();
1909       current = cellScanner.current();
1910       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1911           current.getRowLength(), row2, 0, row2.length));
1912     }
1913   }
1914 
1915   @Test
1916   public void testScanAfterCompaction() throws Exception {
1917     setAuths();
1918     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1919     try (Table table = doPuts(tableName)) {
1920       TEST_UTIL.getHBaseAdmin().flush(tableName);
1921       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1922         @Override
1923         public Void run() throws Exception {
1924           try (Connection connection = ConnectionFactory.createConnection(conf);
1925                Table table = connection.getTable(tableName)) {
1926             Delete d = new Delete(row1);
1927             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|(" +
1928                 SECRET + "&" + TOPSECRET+")"));
1929             d.addFamily(fam, 126l);
1930             table.delete(d);
1931           } catch (Throwable t) {
1932             throw new IOException(t);
1933           }
1934           return null;
1935         }
1936       };
1937       SUPERUSER.runAs(actiona);
1938 
1939       TEST_UTIL.getHBaseAdmin().flush(tableName);
1940       Put put = new Put(Bytes.toBytes("row3"));
1941       put.add(fam, qual, 127l, value);
1942       put.setCellVisibility(new CellVisibility(CONFIDENTIAL + "&" + PRIVATE));
1943       table.put(put);
1944       TEST_UTIL.getHBaseAdmin().flush(tableName);
1945       TEST_UTIL.getHBaseAdmin().compact(tableName);
1946       Thread.sleep(5000);
1947       // Sleep to ensure compaction happens. Need to do it in a better way
1948       Scan s = new Scan();
1949       s.setMaxVersions(5);
1950       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1951       ResultScanner scanner = table.getScanner(s);
1952       Result[] next = scanner.next(3);
1953       assertTrue(next.length == 3);
1954       CellScanner cellScanner = next[0].cellScanner();
1955       cellScanner.advance();
1956       Cell current = cellScanner.current();
1957       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1958           current.getRowLength(), row1, 0, row1.length));
1959       assertEquals(current.getTimestamp(), 127l);
1960       cellScanner = next[1].cellScanner();
1961       cellScanner.advance();
1962       current = cellScanner.current();
1963       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
1964           current.getRowLength(), row2, 0, row2.length));
1965     }
1966   }
1967 
1968   @Test
1969   public void testDeleteFamilySpecificTimeStampWithMulipleVersionsDoneTwice() throws Exception {
1970     setAuths();
1971     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
1972     // Do not flush here.
1973     try (Table table = doPuts(tableName)) {
1974       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
1975         @Override
1976         public Void run() throws Exception {
1977           try (Connection connection = ConnectionFactory.createConnection(conf);
1978                Table table = connection.getTable(tableName)) {
1979             Delete d = new Delete(row1);
1980             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
1981                 + TOPSECRET + "&" + SECRET+")"));
1982             d.addFamily(fam, 125l);
1983             table.delete(d);
1984           } catch (Throwable t) {
1985             throw new IOException(t);
1986           }
1987           return null;
1988         }
1989       };
1990       SUPERUSER.runAs(actiona);
1991 
1992       Scan s = new Scan();
1993       s.setMaxVersions(5);
1994       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
1995       ResultScanner scanner = table.getScanner(s);
1996       Result[] next = scanner.next(3);
1997       assertTrue(next.length == 2);
1998       CellScanner cellScanner = next[0].cellScanner();
1999       cellScanner.advance();
2000       Cell current = cellScanner.current();
2001       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2002           current.getRowLength(), row1, 0, row1.length));
2003       assertEquals(current.getTimestamp(), 127l);
2004       cellScanner.advance();
2005       current = cellScanner.current();
2006       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2007           current.getRowLength(), row1, 0, row1.length));
2008       assertEquals(current.getTimestamp(), 126l);
2009       cellScanner.advance();
2010       current = cellScanner.current();
2011       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2012           current.getRowLength(), row1, 0, row1.length));
2013       assertEquals(current.getTimestamp(), 125l);
2014       cellScanner.advance();
2015       current = cellScanner.current();
2016       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2017           current.getRowLength(), row1, 0, row1.length));
2018       assertEquals(current.getTimestamp(), 123l);
2019       cellScanner = next[1].cellScanner();
2020       cellScanner.advance();
2021       current = cellScanner.current();
2022       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2023           current.getRowLength(), row2, 0, row2.length));
2024 
2025       // Issue 2nd delete
2026       actiona = new PrivilegedExceptionAction<Void>() {
2027         @Override
2028         public Void run() throws Exception {
2029           try (Connection connection = ConnectionFactory.createConnection(conf);
2030                Table table = connection.getTable(tableName)) {
2031             Delete d = new Delete(row1);
2032             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
2033                 + TOPSECRET + "&" + SECRET+")"));
2034             d.addFamily(fam, 127l);
2035             table.delete(d);
2036           } catch (Throwable t) {
2037             throw new IOException(t);
2038           }
2039           return null;
2040         }
2041       };
2042       SUPERUSER.runAs(actiona);
2043       s = new Scan();
2044       s.setMaxVersions(5);
2045       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2046       scanner = table.getScanner(s);
2047       next = scanner.next(3);
2048       assertTrue(next.length == 2);
2049       cellScanner = next[0].cellScanner();
2050       cellScanner.advance();
2051       current = cellScanner.current();
2052       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2053           current.getRowLength(), row1, 0, row1.length));
2054       assertEquals(current.getTimestamp(), 125l);
2055       cellScanner.advance();
2056       current = cellScanner.current();
2057       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2058           current.getRowLength(), row1, 0, row1.length));
2059       assertEquals(current.getTimestamp(), 123l);
2060       cellScanner = next[1].cellScanner();
2061       cellScanner.advance();
2062       current = cellScanner.current();
2063       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2064           current.getRowLength(), row2, 0, row2.length));
2065       assertEquals(current.getTimestamp(), 127l);
2066     }
2067   }
2068 
2069   @Test
2070   public void testMultipleDeleteFamilyVersionWithDiffLabels() throws Exception {
2071     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
2072         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
2073       @Override
2074       public VisibilityLabelsResponse run() throws Exception {
2075         try (Connection conn = ConnectionFactory.createConnection(conf)) {
2076           return VisibilityClient.setAuths(conn, new String[] { CONFIDENTIAL, PRIVATE, SECRET },
2077               SUPERUSER.getShortName());
2078         } catch (Throwable e) {
2079         }
2080         return null;
2081       }
2082     };
2083     VisibilityLabelsResponse response = SUPERUSER.runAs(action);
2084     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2085     try (Table table = doPuts(tableName);) {
2086       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2087         @Override
2088         public Void run() throws Exception {
2089           try (Connection connection = ConnectionFactory.createConnection(conf);
2090                Table table = connection.getTable(tableName)) {
2091             Delete d = new Delete(row1);
2092             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
2093             d.deleteFamilyVersion(fam, 123l);
2094             table.delete(d);
2095             d = new Delete(row1);
2096             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
2097             d.deleteFamilyVersion(fam, 125l);
2098             table.delete(d);
2099           } catch (Throwable t) {
2100             throw new IOException(t);
2101           }
2102           return null;
2103         }
2104       };
2105       SUPERUSER.runAs(actiona);
2106 
2107       TEST_UTIL.getHBaseAdmin().flush(tableName);
2108       Scan s = new Scan();
2109       s.setMaxVersions(5);
2110       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2111       ResultScanner scanner = table.getScanner(s);
2112       Result[] next = scanner.next(5);
2113       assertTrue(next.length == 2);
2114       CellScanner cellScanner = next[0].cellScanner();
2115       cellScanner.advance();
2116       Cell current = cellScanner.current();
2117       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2118           current.getRowLength(), row1, 0, row1.length));
2119       assertEquals(current.getTimestamp(), 127l);
2120       cellScanner.advance();
2121       current = cellScanner.current();
2122       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2123           current.getRowLength(), row1, 0, row1.length));
2124       assertEquals(current.getTimestamp(), 126l);
2125       cellScanner.advance();
2126       current = cellScanner.current();
2127       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2128           current.getRowLength(), row1, 0, row1.length));
2129       assertEquals(current.getTimestamp(), 124l);
2130     }
2131   }
2132 
2133   @Test (timeout=180000)
2134   public void testSpecificDeletesFollowedByDeleteFamily() throws Exception {
2135     setAuths();
2136     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2137     try (Table table = doPuts(tableName)){
2138       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2139         @Override
2140         public Void run() throws Exception {
2141           try (Connection connection = ConnectionFactory.createConnection(conf);
2142                Table table = connection.getTable(tableName)) {
2143             Delete d = new Delete(row1);
2144             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
2145                 + TOPSECRET + "&" + SECRET + ")"));
2146             d.addColumn(fam, qual, 126l);
2147             table.delete(d);
2148             d = new Delete(row1);
2149             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
2150             d.deleteFamilyVersion(fam, 125l);
2151             table.delete(d);
2152           } catch (Throwable t) {
2153             throw new IOException(t);
2154           }
2155           return null;
2156         }
2157       };
2158       SUPERUSER.runAs(actiona);
2159 
2160       TEST_UTIL.getHBaseAdmin().flush(tableName);
2161       Scan s = new Scan();
2162       s.setMaxVersions(5);
2163       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2164       ResultScanner scanner = table.getScanner(s);
2165       Result[] next = scanner.next(5);
2166       assertTrue(next.length == 2);
2167       CellScanner cellScanner = next[0].cellScanner();
2168       cellScanner.advance();
2169       Cell current = cellScanner.current();
2170       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2171           current.getRowLength(), row1, 0, row1.length));
2172       assertEquals(current.getTimestamp(), 127l);
2173       cellScanner.advance();
2174       current = cellScanner.current();
2175       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2176           current.getRowLength(), row1, 0, row1.length));
2177       assertEquals(current.getTimestamp(), 124l);
2178       cellScanner.advance();
2179       current = cellScanner.current();
2180       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2181           current.getRowLength(), row1, 0, row1.length));
2182       assertEquals(current.getTimestamp(), 123l);
2183       // Issue 2nd delete
2184       actiona = new PrivilegedExceptionAction<Void>() {
2185         @Override
2186         public Void run() throws Exception {
2187           try (Connection connection = ConnectionFactory.createConnection(conf);
2188                Table table = connection.getTable(tableName)) {
2189             Delete d = new Delete(row1);
2190             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
2191             d.addFamily(fam);
2192             table.delete(d);
2193           } catch (Throwable t) {
2194             throw new IOException(t);
2195           }
2196           return null;
2197         }
2198       };
2199       SUPERUSER.runAs(actiona);
2200       s = new Scan();
2201       s.setMaxVersions(5);
2202       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2203       scanner = table.getScanner(s);
2204       next = scanner.next(5);
2205       assertTrue(next.length == 2);
2206       cellScanner = next[0].cellScanner();
2207       cellScanner.advance();
2208       current = cellScanner.current();
2209       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2210           current.getRowLength(), row1, 0, row1.length));
2211       assertEquals(current.getTimestamp(), 127l);
2212       cellScanner.advance();
2213       current = cellScanner.current();
2214       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2215           current.getRowLength(), row1, 0, row1.length));
2216       assertEquals(current.getTimestamp(), 124l);
2217     }
2218   }
2219 
2220   @Test(timeout = 180000)
2221   public void testSpecificDeletesFollowedByDeleteFamily1() throws Exception {
2222     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
2223         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
2224       @Override
2225       public VisibilityLabelsResponse run() throws Exception {
2226         try (Connection conn = ConnectionFactory.createConnection(conf)) {
2227           return VisibilityClient.setAuths(conn, new String[] { CONFIDENTIAL,
2228             PRIVATE, SECRET },
2229               SUPERUSER.getShortName());
2230         } catch (Throwable e) {
2231         }
2232         return null;
2233       }
2234     };
2235     VisibilityLabelsResponse response = SUPERUSER.runAs(action);
2236     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2237     try (Table table = doPuts(tableName)){
2238       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2239         @Override
2240         public Void run() throws Exception {
2241           try (Connection connection = ConnectionFactory.createConnection(conf);
2242                Table table = connection.getTable(tableName)) {
2243             Delete d = new Delete(row1);
2244             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
2245                 + TOPSECRET + "&" + SECRET + ")"));
2246             d.addColumn(fam, qual);
2247             table.delete(d);
2248 
2249             d = new Delete(row1);
2250             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
2251             d.deleteFamilyVersion(fam, 125l);
2252             table.delete(d);
2253           } catch (Throwable t) {
2254             throw new IOException(t);
2255           }
2256           return null;
2257         }
2258       };
2259       SUPERUSER.runAs(actiona);
2260 
2261       TEST_UTIL.getHBaseAdmin().flush(tableName);
2262       Scan s = new Scan();
2263       s.setMaxVersions(5);
2264       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2265       ResultScanner scanner = table.getScanner(s);
2266       Result[] next = scanner.next(5);
2267       assertTrue(next.length == 2);
2268       CellScanner cellScanner = next[0].cellScanner();
2269       cellScanner.advance();
2270       Cell current = cellScanner.current();
2271       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2272           current.getRowLength(), row1, 0, row1.length));
2273       assertEquals(current.getTimestamp(), 126l);
2274       cellScanner.advance();
2275       current = cellScanner.current();
2276       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2277           current.getRowLength(), row1, 0, row1.length));
2278       assertEquals(current.getTimestamp(), 124l);
2279       cellScanner.advance();
2280       current = cellScanner.current();
2281       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2282           current.getRowLength(), row1, 0, row1.length));
2283       assertEquals(current.getTimestamp(), 123l);
2284       // Issue 2nd delete
2285       actiona = new PrivilegedExceptionAction<Void>() {
2286         @Override
2287         public Void run() throws Exception {
2288           try (Connection connection = ConnectionFactory.createConnection(conf);
2289                Table table = connection.getTable(tableName)) {
2290             Delete d = new Delete(row1);
2291             d.setCellVisibility(new CellVisibility(CONFIDENTIAL));
2292             d.addFamily(fam);
2293             table.delete(d);
2294           } catch (Throwable t) {
2295             throw new IOException(t);
2296           }
2297           return null;
2298         }
2299       };
2300       SUPERUSER.runAs(actiona);
2301       s = new Scan();
2302       s.setMaxVersions(5);
2303       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2304       scanner = table.getScanner(s);
2305       next = scanner.next(5);
2306       assertTrue(next.length == 2);
2307       cellScanner = next[0].cellScanner();
2308       cellScanner.advance();
2309       current = cellScanner.current();
2310       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2311           current.getRowLength(), row1, 0, row1.length));
2312       assertEquals(current.getTimestamp(), 126l);
2313       cellScanner.advance();
2314       current = cellScanner.current();
2315       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2316           current.getRowLength(), row1, 0, row1.length));
2317       assertEquals(current.getTimestamp(), 124l);
2318     }
2319   }
2320 
2321   @Test
2322   public void testDeleteColumnSpecificTimeStampWithMulipleVersionsDoneTwice() throws Exception {
2323     setAuths();
2324     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2325     try (Table table = doPuts(tableName)) {
2326       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2327         @Override
2328         public Void run() throws Exception {
2329           try (Connection connection = ConnectionFactory.createConnection(conf);
2330                Table table = connection.getTable(tableName)) {
2331             Delete d = new Delete(row1);
2332             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
2333             d.addColumn(fam, qual, 125l);
2334             table.delete(d);
2335           } catch (Throwable t) {
2336             throw new IOException(t);
2337           }
2338           return null;
2339         }
2340       };
2341       SUPERUSER.runAs(actiona);
2342 
2343       Scan s = new Scan();
2344       s.setMaxVersions(5);
2345       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2346       ResultScanner scanner = table.getScanner(s);
2347       Result[] next = scanner.next(3);
2348       assertTrue(next.length == 2);
2349       CellScanner cellScanner = next[0].cellScanner();
2350       cellScanner.advance();
2351       Cell current = cellScanner.current();
2352       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2353           current.getRowLength(), row1, 0, row1.length));
2354       assertEquals(current.getTimestamp(), 127l);
2355       cellScanner.advance();
2356       current = cellScanner.current();
2357       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2358           current.getRowLength(), row1, 0, row1.length));
2359       assertEquals(current.getTimestamp(), 126l);
2360       cellScanner.advance();
2361       current = cellScanner.current();
2362       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2363           current.getRowLength(), row1, 0, row1.length));
2364       assertEquals(current.getTimestamp(), 124l);
2365       cellScanner.advance();
2366       current = cellScanner.current();
2367       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2368           current.getRowLength(), row1, 0, row1.length));
2369       assertEquals(current.getTimestamp(), 123l);
2370       cellScanner = next[1].cellScanner();
2371       cellScanner.advance();
2372       current = cellScanner.current();
2373       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2374           current.getRowLength(), row2, 0, row2.length));
2375 
2376       // Issue 2nd delete
2377       actiona = new PrivilegedExceptionAction<Void>() {
2378         @Override
2379         public Void run() throws Exception {
2380           try (Connection connection = ConnectionFactory.createConnection(conf);
2381                Table table = connection.getTable(tableName)) {
2382             Delete d = new Delete(row1);
2383             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
2384                 + TOPSECRET + "&" + SECRET+")"));
2385             d.addColumn(fam, qual, 127l);
2386             table.delete(d);
2387           } catch (Throwable t) {
2388             throw new IOException(t);
2389           }
2390           return null;
2391         }
2392       };
2393       SUPERUSER.runAs(actiona);
2394       s = new Scan();
2395       s.setMaxVersions(5);
2396       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2397       scanner = table.getScanner(s);
2398       next = scanner.next(3);
2399       assertTrue(next.length == 2);
2400       cellScanner = next[0].cellScanner();
2401       cellScanner.advance();
2402       current = cellScanner.current();
2403       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2404           current.getRowLength(), row1, 0, row1.length));
2405       assertEquals(current.getTimestamp(), 126l);
2406       cellScanner.advance();
2407       current = cellScanner.current();
2408       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2409           current.getRowLength(), row1, 0, row1.length));
2410       assertEquals(current.getTimestamp(), 124l);
2411       cellScanner.advance();
2412       current = cellScanner.current();
2413       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2414           current.getRowLength(), row1, 0, row1.length));
2415       assertEquals(current.getTimestamp(), 123l);
2416       cellScanner = next[1].cellScanner();
2417       cellScanner.advance();
2418       current = cellScanner.current();
2419       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2420           current.getRowLength(), row2, 0, row2.length));
2421       assertEquals(current.getTimestamp(), 127l);
2422     }
2423   }
2424 
2425   @Test
2426   public void testDeleteColumnSpecificTimeStampWithMulipleVersionsDoneTwice1() throws Exception {
2427     setAuths();
2428     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2429     // Do not flush here.
2430     try (Table table = doPuts(tableName)) {
2431       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2432         @Override
2433         public Void run() throws Exception {
2434           try (Connection connection = ConnectionFactory.createConnection(conf);
2435                Table table = connection.getTable(tableName)) {
2436             Delete d = new Delete(row1);
2437             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")" +
2438                 "|(" + TOPSECRET + "&" + SECRET + ")"));
2439             d.addColumn(fam, qual, 127l);
2440             table.delete(d);
2441           } catch (Throwable t) {
2442             throw new IOException(t);
2443           }
2444           return null;
2445         }
2446       };
2447       SUPERUSER.runAs(actiona);
2448 
2449       Scan s = new Scan();
2450       s.setMaxVersions(5);
2451       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2452       ResultScanner scanner = table.getScanner(s);
2453       Result[] next = scanner.next(3);
2454       assertTrue(next.length == 2);
2455       CellScanner cellScanner = next[0].cellScanner();
2456       cellScanner.advance();
2457       Cell current = cellScanner.current();
2458       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2459           current.getRowLength(), row1, 0, row1.length));
2460       assertEquals(current.getTimestamp(), 126l);
2461       cellScanner.advance();
2462       current = cellScanner.current();
2463       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2464           current.getRowLength(), row1, 0, row1.length));
2465       assertEquals(current.getTimestamp(), 125l);
2466       cellScanner.advance();
2467       current = cellScanner.current();
2468       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2469           current.getRowLength(), row1, 0, row1.length));
2470       assertEquals(current.getTimestamp(), 124l);
2471       cellScanner.advance();
2472       current = cellScanner.current();
2473       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2474           current.getRowLength(), row1, 0, row1.length));
2475       assertEquals(current.getTimestamp(), 123l);
2476       cellScanner = next[1].cellScanner();
2477       cellScanner.advance();
2478       current = cellScanner.current();
2479       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2480           current.getRowLength(), row2, 0, row2.length));
2481 
2482       // Issue 2nd delete
2483       actiona = new PrivilegedExceptionAction<Void>() {
2484         @Override
2485         public Void run() throws Exception {
2486           try (Connection connection = ConnectionFactory.createConnection(conf);
2487                Table table = connection.getTable(tableName)) {
2488             Delete d = new Delete(row1);
2489             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
2490             d.addColumn(fam, qual, 127l);
2491             table.delete(d);
2492           } catch (Throwable t) {
2493             throw new IOException(t);
2494           }
2495           return null;
2496         }
2497       };
2498       SUPERUSER.runAs(actiona);
2499       s = new Scan();
2500       s.setMaxVersions(5);
2501       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2502       scanner = table.getScanner(s);
2503       next = scanner.next(3);
2504       assertTrue(next.length == 2);
2505       cellScanner = next[0].cellScanner();
2506       cellScanner.advance();
2507       current = cellScanner.current();
2508       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2509           current.getRowLength(), row1, 0, row1.length));
2510       assertEquals(current.getTimestamp(), 126l);
2511       cellScanner.advance();
2512       current = cellScanner.current();
2513       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2514           current.getRowLength(), row1, 0, row1.length));
2515       assertEquals(current.getTimestamp(), 125l);
2516       cellScanner.advance();
2517       current = cellScanner.current();
2518       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2519           current.getRowLength(), row1, 0, row1.length));
2520       assertEquals(current.getTimestamp(), 124l);
2521       cellScanner.advance();
2522       current = cellScanner.current();
2523       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2524           current.getRowLength(), row1, 0, row1.length));
2525       assertEquals(current.getTimestamp(), 123l);
2526       cellScanner = next[1].cellScanner();
2527       cellScanner.advance();
2528       current = cellScanner.current();
2529       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2530           current.getRowLength(), row2, 0, row2.length));
2531       assertEquals(current.getTimestamp(), 127l);
2532     }
2533   }
2534   @Test
2535   public void testDeleteColumnSpecificTimeStampWithMulipleVersionsDoneTwice2() throws Exception {
2536     setAuths();
2537     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2538 
2539     // Do not flush here.
2540     try (Table table = doPuts(tableName)) {
2541       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2542         @Override
2543         public Void run() throws Exception {
2544           try (Connection connection = ConnectionFactory.createConnection(conf);
2545                Table table = connection.getTable(tableName)) {
2546             Delete d = new Delete(row1);
2547             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
2548                 + TOPSECRET + "&" + SECRET+")"));
2549             d.addColumn(fam, qual, 125l);
2550             table.delete(d);
2551           } catch (Throwable t) {
2552             throw new IOException(t);
2553           }
2554           return null;
2555         }
2556       };
2557       SUPERUSER.runAs(actiona);
2558 
2559       Scan s = new Scan();
2560       s.setMaxVersions(5);
2561       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2562       ResultScanner scanner = table.getScanner(s);
2563       Result[] next = scanner.next(3);
2564       assertTrue(next.length == 2);
2565       CellScanner cellScanner = next[0].cellScanner();
2566       cellScanner.advance();
2567       Cell current = cellScanner.current();
2568       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2569           current.getRowLength(), row1, 0, row1.length));
2570       assertEquals(current.getTimestamp(), 127l);
2571       cellScanner.advance();
2572       current = cellScanner.current();
2573       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2574           current.getRowLength(), row1, 0, row1.length));
2575       assertEquals(current.getTimestamp(), 126l);
2576       cellScanner.advance();
2577       current = cellScanner.current();
2578       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2579           current.getRowLength(), row1, 0, row1.length));
2580       assertEquals(current.getTimestamp(), 125l);
2581       cellScanner.advance();
2582       current = cellScanner.current();
2583       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2584           current.getRowLength(), row1, 0, row1.length));
2585       assertEquals(current.getTimestamp(), 124l);
2586       cellScanner.advance();
2587       current = cellScanner.current();
2588       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2589           current.getRowLength(), row1, 0, row1.length));
2590       assertEquals(current.getTimestamp(), 123l);
2591       cellScanner = next[1].cellScanner();
2592       cellScanner.advance();
2593       current = cellScanner.current();
2594       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2595           current.getRowLength(), row2, 0, row2.length));
2596 
2597       // Issue 2nd delete
2598       actiona = new PrivilegedExceptionAction<Void>() {
2599         @Override
2600         public Void run() throws Exception {
2601           try (Connection connection = ConnectionFactory.createConnection(conf);
2602                Table table = connection.getTable(tableName)) {
2603             Delete d = new Delete(row1);
2604             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
2605                 + TOPSECRET + "&" + SECRET+")"));
2606             d.addColumn(fam, qual, 127l);
2607             table.delete(d);
2608           } catch (Throwable t) {
2609             throw new IOException(t);
2610           }
2611           return null;
2612         }
2613       };
2614       SUPERUSER.runAs(actiona);
2615       s = new Scan();
2616       s.setMaxVersions(5);
2617       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2618       scanner = table.getScanner(s);
2619       next = scanner.next(3);
2620       assertTrue(next.length == 2);
2621       cellScanner = next[0].cellScanner();
2622       cellScanner.advance();
2623       current = cellScanner.current();
2624       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2625           current.getRowLength(), row1, 0, row1.length));
2626       assertEquals(current.getTimestamp(), 126l);
2627       cellScanner.advance();
2628       current = cellScanner.current();
2629       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2630           current.getRowLength(), row1, 0, row1.length));
2631       assertEquals(current.getTimestamp(), 125l);
2632       cellScanner.advance();
2633       current = cellScanner.current();
2634       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2635           current.getRowLength(), row1, 0, row1.length));
2636       assertEquals(current.getTimestamp(), 124l);
2637       cellScanner.advance();
2638       current = cellScanner.current();
2639       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2640           current.getRowLength(), row1, 0, row1.length));
2641       assertEquals(current.getTimestamp(), 123l);
2642       cellScanner = next[1].cellScanner();
2643       cellScanner.advance();
2644       current = cellScanner.current();
2645       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2646           current.getRowLength(), row2, 0, row2.length));
2647       assertEquals(current.getTimestamp(), 127l);
2648     }
2649   }
2650   @Test
2651   public void testDeleteColumnAndDeleteFamilylSpecificTimeStampWithMulipleVersion()
2652       throws Exception {
2653     setAuths();
2654     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2655     // Do not flush here.
2656     try (Table table = doPuts(tableName)) {
2657       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2658         @Override
2659         public Void run() throws Exception {
2660           try (Connection connection = ConnectionFactory.createConnection(conf);
2661                Table table = connection.getTable(tableName)) {
2662             Delete d = new Delete(row1);
2663             d.setCellVisibility(new CellVisibility(SECRET + "&" + TOPSECRET));
2664             d.addColumn(fam, qual, 125l);
2665             table.delete(d);
2666           } catch (Throwable t) {
2667             throw new IOException(t);
2668           }
2669           return null;
2670         }
2671       };
2672       SUPERUSER.runAs(actiona);
2673 
2674       Scan s = new Scan();
2675       s.setMaxVersions(5);
2676       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2677       ResultScanner scanner = table.getScanner(s);
2678       Result[] next = scanner.next(3);
2679       assertTrue(next.length == 2);
2680       CellScanner cellScanner = next[0].cellScanner();
2681       cellScanner.advance();
2682       Cell current = cellScanner.current();
2683       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2684           current.getRowLength(), row1, 0, row1.length));
2685       assertEquals(current.getTimestamp(), 127l);
2686       cellScanner.advance();
2687       current = cellScanner.current();
2688       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2689           current.getRowLength(), row1, 0, row1.length));
2690       assertEquals(current.getTimestamp(), 126l);
2691       cellScanner.advance();
2692       current = cellScanner.current();
2693       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2694           current.getRowLength(), row1, 0, row1.length));
2695       assertEquals(current.getTimestamp(), 124l);
2696       cellScanner.advance();
2697       current = cellScanner.current();
2698       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2699           current.getRowLength(), row1, 0, row1.length));
2700       assertEquals(current.getTimestamp(), 123l);
2701       cellScanner = next[1].cellScanner();
2702       cellScanner.advance();
2703       current = cellScanner.current();
2704       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2705           current.getRowLength(), row2, 0, row2.length));
2706 
2707       // Issue 2nd delete
2708       actiona = new PrivilegedExceptionAction<Void>() {
2709         @Override
2710         public Void run() throws Exception {
2711           try (Connection connection = ConnectionFactory.createConnection(conf);
2712                Table table = connection.getTable(tableName)) {
2713             Delete d = new Delete(row1);
2714             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
2715                 + TOPSECRET + "&" + SECRET+")"));
2716             d.addFamily(fam, 124l);
2717             table.delete(d);
2718           } catch (Throwable t) {
2719             throw new IOException(t);
2720           }
2721           return null;
2722         }
2723       };
2724       SUPERUSER.runAs(actiona);
2725       s = new Scan();
2726       s.setMaxVersions(5);
2727       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2728       scanner = table.getScanner(s);
2729       next = scanner.next(3);
2730       assertTrue(next.length == 2);
2731       cellScanner = next[0].cellScanner();
2732       cellScanner.advance();
2733       current = cellScanner.current();
2734       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2735           current.getRowLength(), row1, 0, row1.length));
2736       assertEquals(current.getTimestamp(), 127l);
2737       cellScanner.advance();
2738       current = cellScanner.current();
2739       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2740           current.getRowLength(), row1, 0, row1.length));
2741       assertEquals(current.getTimestamp(), 126l);
2742       cellScanner = next[1].cellScanner();
2743       cellScanner.advance();
2744       current = cellScanner.current();
2745       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2746           current.getRowLength(), row2, 0, row2.length));
2747       assertEquals(current.getTimestamp(), 127l);
2748     }
2749   }
2750 
2751   private void setAuths() throws IOException, InterruptedException {
2752     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
2753         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
2754       @Override
2755       public VisibilityLabelsResponse run() throws Exception {
2756         try (Connection conn = ConnectionFactory.createConnection(conf)) {
2757           return VisibilityClient.setAuths(conn, new String[] { CONFIDENTIAL,
2758             PRIVATE, SECRET,
2759               TOPSECRET }, SUPERUSER.getShortName());
2760         } catch (Throwable e) {
2761         }
2762         return null;
2763       }
2764     };
2765     SUPERUSER.runAs(action);
2766   }
2767 
2768   @Test
2769   public void testDiffDeleteTypesForTheSameCellUsingMultipleVersions() throws Exception {
2770     setAuths();
2771     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2772     try (Table table = doPuts(tableName)){
2773       // Do not flush here.
2774       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2775         @Override
2776         public Void run() throws Exception {
2777           try (Connection connection = ConnectionFactory.createConnection(conf);
2778                Table table = connection.getTable(tableName)) {
2779             Delete d = new Delete(row1);
2780             d.setCellVisibility(new CellVisibility("(" + PRIVATE + "&" + CONFIDENTIAL + ")|("
2781                 + TOPSECRET + "&" + SECRET+")"));
2782             d.addColumns(fam, qual, 125l);
2783             table.delete(d);
2784           } catch (Throwable t) {
2785             throw new IOException(t);
2786           }
2787           return null;
2788         }
2789       };
2790       SUPERUSER.runAs(actiona);
2791 
2792       Scan s = new Scan();
2793       s.setMaxVersions(5);
2794       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2795       ResultScanner scanner = table.getScanner(s);
2796       Result[] next = scanner.next(3);
2797       assertTrue(next.length == 2);
2798       CellScanner cellScanner = next[0].cellScanner();
2799       cellScanner.advance();
2800       Cell current = cellScanner.current();
2801       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2802           current.getRowLength(), row1, 0, row1.length));
2803       assertEquals(current.getTimestamp(), 127l);
2804       cellScanner.advance();
2805       current = cellScanner.current();
2806       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2807           current.getRowLength(), row1, 0, row1.length));
2808       assertEquals(current.getTimestamp(), 126l);
2809       cellScanner.advance();
2810       current = cellScanner.current();
2811       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2812           current.getRowLength(), row1, 0, row1.length));
2813       assertEquals(current.getTimestamp(), 125l);
2814       cellScanner.advance();
2815       current = cellScanner.current();
2816       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2817           current.getRowLength(), row1, 0, row1.length));
2818       assertEquals(current.getTimestamp(), 123l);
2819       cellScanner = next[1].cellScanner();
2820       cellScanner.advance();
2821       current = cellScanner.current();
2822       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2823           current.getRowLength(), row2, 0, row2.length));
2824 
2825       // Issue 2nd delete
2826       actiona = new PrivilegedExceptionAction<Void>() {
2827         @Override
2828         public Void run() throws Exception {
2829           try (Connection connection = ConnectionFactory.createConnection(conf);
2830                Table table = connection.getTable(tableName)) {
2831             Delete d = new Delete(row1);
2832             d.setCellVisibility(new CellVisibility("(" + CONFIDENTIAL + "&" + PRIVATE + ")|("
2833                 + TOPSECRET + "&" + SECRET+")"));
2834             d.addColumn(fam, qual, 127l);
2835             table.delete(d);
2836           } catch (Throwable t) {
2837             throw new IOException(t);
2838           }
2839           return null;
2840         }
2841       };
2842       SUPERUSER.runAs(actiona);
2843       s = new Scan();
2844       s.setMaxVersions(5);
2845       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2846       scanner = table.getScanner(s);
2847       next = scanner.next(3);
2848       assertTrue(next.length == 2);
2849       cellScanner = next[0].cellScanner();
2850       cellScanner.advance();
2851       current = cellScanner.current();
2852       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2853           current.getRowLength(), row1, 0, row1.length));
2854       assertEquals(current.getTimestamp(), 126l);
2855       cellScanner.advance();
2856       current = cellScanner.current();
2857       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2858           current.getRowLength(), row1, 0, row1.length));
2859       assertEquals(current.getTimestamp(), 125l);
2860       cellScanner.advance();
2861       current = cellScanner.current();
2862       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2863           current.getRowLength(), row1, 0, row1.length));
2864       assertEquals(current.getTimestamp(), 123l);
2865       cellScanner = next[1].cellScanner();
2866       cellScanner.advance();
2867       current = cellScanner.current();
2868       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
2869           current.getRowLength(), row2, 0, row2.length));
2870     }
2871   }
2872 
2873   @Test
2874   public void testDeleteColumnLatestWithNoCellVisibility() throws Exception {
2875     setAuths();
2876     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
2877     try (Table table = doPuts(tableName)){
2878       TEST_UTIL.getHBaseAdmin().flush(tableName);
2879       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
2880         @Override
2881         public Void run() throws Exception {
2882           try (Connection connection = ConnectionFactory.createConnection(conf);
2883                Table table = connection.getTable(tableName)) {
2884             Delete d = new Delete(row1);
2885             d.addColumn(fam, qual, 125l);
2886             table.delete(d);
2887           } catch (Throwable t) {
2888             throw new IOException(t);
2889           }
2890           return null;
2891         }
2892       };
2893       SUPERUSER.runAs(actiona);
2894 
2895       TEST_UTIL.getHBaseAdmin().flush(tableName);
2896       Scan s = new Scan();
2897       s.setMaxVersions(5);
2898       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2899       ResultScanner scanner = table.getScanner(s);
2900       Result[] next = scanner.next(3);
2901       assertTrue(next.length == 2);
2902       scanAll(next);
2903       actiona = new PrivilegedExceptionAction<Void>() {
2904         @Override
2905         public Void run() throws Exception {
2906           try (Connection connection = ConnectionFactory.createConnection(conf);
2907                Table table = connection.getTable(tableName)) {
2908             Delete d = new Delete(row1);
2909             d.addColumns(fam, qual, 125l);
2910             table.delete(d);
2911           } catch (Throwable t) {
2912             throw new IOException(t);
2913           }
2914           return null;
2915         }
2916       };
2917       SUPERUSER.runAs(actiona);
2918 
2919       TEST_UTIL.getHBaseAdmin().flush(tableName);
2920       s = new Scan();
2921       s.setMaxVersions(5);
2922       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2923       scanner = table.getScanner(s);
2924       next = scanner.next(3);
2925       assertTrue(next.length == 2);
2926       scanAll(next);
2927 
2928       actiona = new PrivilegedExceptionAction<Void>() {
2929         @Override
2930         public Void run() throws Exception {
2931           try (Connection connection = ConnectionFactory.createConnection(conf);
2932                Table table = connection.getTable(tableName)) {
2933             Delete d = new Delete(row1);
2934             d.addFamily(fam, 125l);
2935             table.delete(d);
2936           } catch (Throwable t) {
2937             throw new IOException(t);
2938           }
2939           return null;
2940         }
2941       };
2942       SUPERUSER.runAs(actiona);
2943 
2944       TEST_UTIL.getHBaseAdmin().flush(tableName);
2945       s = new Scan();
2946       s.setMaxVersions(5);
2947       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2948       scanner = table.getScanner(s);
2949       next = scanner.next(3);
2950       assertTrue(next.length == 2);
2951       scanAll(next);
2952 
2953       actiona = new PrivilegedExceptionAction<Void>() {
2954         @Override
2955         public Void run() throws Exception {
2956           try (Connection connection = ConnectionFactory.createConnection(conf);
2957                Table table = connection.getTable(tableName)) {
2958             Delete d = new Delete(row1);
2959             d.addFamily(fam);
2960             table.delete(d);
2961           } catch (Throwable t) {
2962             throw new IOException(t);
2963           }
2964           return null;
2965         }
2966       };
2967       SUPERUSER.runAs(actiona);
2968 
2969       TEST_UTIL.getHBaseAdmin().flush(tableName);
2970       s = new Scan();
2971       s.setMaxVersions(5);
2972       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2973       scanner = table.getScanner(s);
2974       next = scanner.next(3);
2975       assertTrue(next.length == 2);
2976       scanAll(next);
2977 
2978       actiona = new PrivilegedExceptionAction<Void>() {
2979         @Override
2980         public Void run() throws Exception {
2981           try (Connection connection = ConnectionFactory.createConnection(conf);
2982                Table table = connection.getTable(tableName)) {
2983             Delete d = new Delete(row1);
2984             d.addColumns(fam, qual);
2985             table.delete(d);
2986           } catch (Throwable t) {
2987             throw new IOException(t);
2988           }
2989           return null;
2990         }
2991       };
2992       SUPERUSER.runAs(actiona);
2993 
2994       TEST_UTIL.getHBaseAdmin().flush(tableName);
2995       s = new Scan();
2996       s.setMaxVersions(5);
2997       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
2998       scanner = table.getScanner(s);
2999       next = scanner.next(3);
3000       assertTrue(next.length == 2);
3001       scanAll(next);
3002 
3003       actiona = new PrivilegedExceptionAction<Void>() {
3004         @Override
3005         public Void run() throws Exception {
3006           try (Connection connection = ConnectionFactory.createConnection(conf);
3007                Table table = connection.getTable(tableName)) {
3008             Delete d = new Delete(row1);
3009             d.deleteFamilyVersion(fam, 126l);
3010             table.delete(d);
3011           } catch (Throwable t) {
3012             throw new IOException(t);
3013           }
3014           return null;
3015         }
3016       };
3017       SUPERUSER.runAs(actiona);
3018 
3019       TEST_UTIL.getHBaseAdmin().flush(tableName);
3020       s = new Scan();
3021       s.setMaxVersions(5);
3022       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
3023       scanner = table.getScanner(s);
3024       next = scanner.next(3);
3025       assertTrue(next.length == 2);
3026       scanAll(next);
3027     }
3028   }
3029 
3030   @Test
3031   public void testDeleteWithNoVisibilitiesForPutsAndDeletes() throws Exception {
3032     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
3033     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
3034     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
3035     colDesc.setMaxVersions(5);
3036     HTableDescriptor desc = new HTableDescriptor(tableName);
3037     desc.addFamily(colDesc);
3038     hBaseAdmin.createTable(desc);
3039     Put p = new Put (Bytes.toBytes("row1"));
3040     p.addColumn(fam, qual, value);
3041     Table table = TEST_UTIL.getConnection().getTable(tableName);
3042     table.put(p);
3043     p = new Put (Bytes.toBytes("row1"));
3044     p.addColumn(fam, qual1, value);
3045     table.put(p);
3046     p = new Put (Bytes.toBytes("row2"));
3047     p.addColumn(fam, qual, value);
3048     table.put(p);
3049     p = new Put (Bytes.toBytes("row2"));
3050     p.addColumn(fam, qual1, value);
3051     table.put(p);
3052     Delete d = new Delete(Bytes.toBytes("row1"));
3053     table.delete(d);
3054     Get g = new Get(Bytes.toBytes("row1"));
3055     g.setMaxVersions();
3056     g.setAuthorizations(new Authorizations(SECRET, PRIVATE));
3057     Result result = table.get(g);
3058     assertEquals(0, result.rawCells().length);
3059 
3060     p = new Put (Bytes.toBytes("row1"));
3061     p.addColumn(fam, qual, value);
3062     table.put(p);
3063     result = table.get(g);
3064     assertEquals(1, result.rawCells().length);
3065   }
3066 
3067   @Test
3068   public void testDeleteWithFamilyDeletesOfSameTsButDifferentVisibilities() throws Exception {
3069     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
3070     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
3071     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
3072     colDesc.setMaxVersions(5);
3073     HTableDescriptor desc = new HTableDescriptor(tableName);
3074     desc.addFamily(colDesc);
3075     hBaseAdmin.createTable(desc);
3076     Table table = TEST_UTIL.getConnection().getTable(tableName);
3077     long t1 = 1234L;
3078     CellVisibility cellVisibility1 = new CellVisibility(SECRET);
3079     CellVisibility cellVisibility2 = new CellVisibility(PRIVATE);
3080     // Cell row1:info:qual:1234 with visibility SECRET
3081     Put p = new Put(row1);
3082     p.addColumn(fam, qual, t1, value);
3083     p.setCellVisibility(cellVisibility1);
3084     table.put(p);
3085 
3086     // Cell row1:info:qual1:1234 with visibility PRIVATE
3087     p = new Put(row1);
3088     p.addColumn(fam, qual1, t1, value);
3089     p.setCellVisibility(cellVisibility2);
3090     table.put(p);
3091 
3092     Delete d = new Delete(row1);
3093     d.addFamily(fam, t1);
3094     d.setCellVisibility(cellVisibility2);
3095     table.delete(d);
3096     d = new Delete(row1);
3097     d.addFamily(fam, t1);
3098     d.setCellVisibility(cellVisibility1);
3099     table.delete(d);
3100 
3101     Get g = new Get(row1);
3102     g.setMaxVersions();
3103     g.setAuthorizations(new Authorizations(SECRET, PRIVATE));
3104     Result result = table.get(g);
3105     assertEquals(0, result.rawCells().length);
3106 
3107     // Cell row2:info:qual:1234 with visibility SECRET
3108     p = new Put(row2);
3109     p.addColumn(fam, qual, t1, value);
3110     p.setCellVisibility(cellVisibility1);
3111     table.put(p);
3112 
3113     // Cell row2:info:qual1:1234 with visibility PRIVATE
3114     p = new Put(row2);
3115     p.addColumn(fam, qual1, t1, value);
3116     p.setCellVisibility(cellVisibility2);
3117     table.put(p);
3118 
3119     d = new Delete(row2);
3120     d.addFamilyVersion(fam, t1);
3121     d.setCellVisibility(cellVisibility2);
3122     table.delete(d);
3123     d = new Delete(row2);
3124     d.addFamilyVersion(fam, t1);
3125     d.setCellVisibility(cellVisibility1);
3126     table.delete(d);
3127 
3128     g = new Get(row2);
3129     g.setMaxVersions();
3130     g.setAuthorizations(new Authorizations(SECRET, PRIVATE));
3131     result = table.get(g);
3132     assertEquals(0, result.rawCells().length);
3133   }
3134 
3135   private void scanAll(Result[] next) throws IOException {
3136     CellScanner cellScanner = next[0].cellScanner();
3137     cellScanner.advance();
3138     Cell current = cellScanner.current();
3139     assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), current.getRowLength(),
3140         row1, 0, row1.length));
3141     assertEquals(current.getTimestamp(), 127l);
3142     cellScanner.advance();
3143     current = cellScanner.current();
3144     assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), current.getRowLength(),
3145         row1, 0, row1.length));
3146     assertEquals(current.getTimestamp(), 126l);
3147     cellScanner.advance();
3148     current = cellScanner.current();
3149     assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), current.getRowLength(),
3150         row1, 0, row1.length));
3151     assertEquals(current.getTimestamp(), 125l);
3152     cellScanner.advance();
3153     current = cellScanner.current();
3154     assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), current.getRowLength(),
3155         row1, 0, row1.length));
3156     assertEquals(current.getTimestamp(), 124l);
3157     cellScanner.advance();
3158     current = cellScanner.current();
3159     assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), current.getRowLength(),
3160         row1, 0, row1.length));
3161     assertEquals(current.getTimestamp(), 123l);
3162     cellScanner = next[1].cellScanner();
3163     cellScanner.advance();
3164     current = cellScanner.current();
3165     assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(), current.getRowLength(),
3166         row2, 0, row2.length));
3167   }
3168 
3169   @Test
3170   public void testVisibilityExpressionWithNotEqualORCondition() throws Exception {
3171     setAuths();
3172     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
3173     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
3174     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
3175     colDesc.setMaxVersions(5);
3176     HTableDescriptor desc = new HTableDescriptor(tableName);
3177     desc.addFamily(colDesc);
3178     hBaseAdmin.createTable(desc);
3179     try (Table table = new HTable(conf, tableName)) {
3180       Put put = new Put(Bytes.toBytes("row1"));
3181       put.add(fam, qual, 123l, value);
3182       put.setCellVisibility(new CellVisibility(CONFIDENTIAL));
3183       table.put(put);
3184       put = new Put(Bytes.toBytes("row1"));
3185       put.add(fam, qual, 124l, value);
3186       put.setCellVisibility(new CellVisibility(CONFIDENTIAL + "|" + PRIVATE));
3187       table.put(put);
3188       TEST_UTIL.getHBaseAdmin().flush(tableName);
3189       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
3190         @Override
3191         public Void run() throws Exception {
3192           try (Connection connection = ConnectionFactory.createConnection(conf);
3193                Table table = connection.getTable(tableName)) {
3194             Delete d = new Delete(row1);
3195             d.addColumn(fam, qual, 124l);
3196             d.setCellVisibility(new CellVisibility(PRIVATE ));
3197             table.delete(d);
3198           } catch (Throwable t) {
3199             throw new IOException(t);
3200           }
3201           return null;
3202         }
3203       };
3204       SUPERUSER.runAs(actiona);
3205 
3206       TEST_UTIL.getHBaseAdmin().flush(tableName);
3207       Scan s = new Scan();
3208       s.setMaxVersions(5);
3209       s.setAuthorizations(new Authorizations(SECRET, PRIVATE, CONFIDENTIAL, TOPSECRET));
3210       ResultScanner scanner = table.getScanner(s);
3211       Result[] next = scanner.next(3);
3212       assertTrue(next.length == 1);
3213       CellScanner cellScanner = next[0].cellScanner();
3214       cellScanner.advance();
3215       Cell current = cellScanner.current();
3216       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
3217           current.getRowLength(), row1, 0, row1.length));
3218       assertEquals(current.getTimestamp(), 124l);
3219       cellScanner.advance();
3220       current = cellScanner.current();
3221       assertTrue(Bytes.equals(current.getRowArray(), current.getRowOffset(),
3222           current.getRowLength(), row1, 0, row1.length));
3223       assertEquals(current.getTimestamp(), 123l);
3224     }
3225   }
3226 
3227   public static Table createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)
3228       throws Exception {
3229     Table table = null;
3230     table = TEST_UTIL.createTable(tableName, fam);
3231     int i = 1;
3232     List<Put> puts = new ArrayList<Put>();
3233     for (String labelExp : labelExps) {
3234       Put put = new Put(Bytes.toBytes("row" + i));
3235       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
3236       put.setCellVisibility(new CellVisibility(labelExp));
3237       puts.add(put);
3238       table.put(put);
3239       i++;
3240     }
3241     // table.put(puts);
3242     return table;
3243   }
3244 
3245   public static Table createTableAndWriteDataWithLabels(TableName tableName, long[] timestamp,
3246       String... labelExps) throws Exception {
3247     Table table = null;
3248     table = TEST_UTIL.createTable(tableName, fam);
3249     int i = 1;
3250     List<Put> puts = new ArrayList<Put>();
3251     for (String labelExp : labelExps) {
3252       Put put = new Put(Bytes.toBytes("row" + i));
3253       put.add(fam, qual, timestamp[i - 1], value);
3254       put.setCellVisibility(new CellVisibility(labelExp));
3255       puts.add(put);
3256       table.put(put);
3257       TEST_UTIL.getHBaseAdmin().flush(tableName);
3258       i++;
3259     }
3260     return table;
3261   }
3262 
3263   public static void addLabels() throws Exception {
3264     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
3265         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
3266       @Override
3267       public VisibilityLabelsResponse run() throws Exception {
3268         String[] labels = { SECRET, TOPSECRET, CONFIDENTIAL, PUBLIC, PRIVATE };
3269         try (Connection conn = ConnectionFactory.createConnection(conf)) {
3270           VisibilityClient.addLabels(conn, labels);
3271         } catch (Throwable t) {
3272           throw new IOException(t);
3273         }
3274         return null;
3275       }
3276     };
3277     SUPERUSER.runAs(action);
3278   }
3279   
3280   @SafeVarargs
3281   public static <T> List<T> createList(T... ts) {
3282     return new ArrayList<>(Arrays.asList(ts));
3283   }
3284 
3285 
3286   private enum DeleteMark {
3287     ROW,
3288     FAMILY,
3289     FAMILY_VERSION,
3290     COLUMN,
3291     CELL
3292   }
3293 
3294   private static Delete addDeleteMark(Delete d, DeleteMark mark, long now) {
3295     switch (mark) {
3296       case ROW:
3297         break;
3298       case FAMILY:
3299         d.addFamily(fam);
3300         break;
3301       case FAMILY_VERSION:
3302         d.addFamilyVersion(fam, now);
3303         break;
3304       case COLUMN:
3305         d.addColumns(fam, qual);
3306         break;
3307       case CELL:
3308         d.addColumn(fam, qual);
3309         break;
3310       default:
3311         break;
3312     }
3313     return d;
3314   }
3315 
3316   @Test
3317   public void testDeleteCellWithoutVisibility() throws IOException, InterruptedException {
3318     for (DeleteMark mark : DeleteMark.values()) {
3319       testDeleteCellWithoutVisibility(mark);
3320     }
3321   }
3322 
3323   private void testDeleteCellWithoutVisibility(DeleteMark mark) throws IOException, InterruptedException {
3324     setAuths();
3325     final TableName tableName = TableName.valueOf("testDeleteCellWithoutVisibility-" + mark.name());
3326     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
3327     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
3328     colDesc.setMaxVersions(5);
3329     HTableDescriptor desc = new HTableDescriptor(tableName);
3330     desc.addFamily(colDesc);
3331     hBaseAdmin.createTable(desc);
3332     long now = System.currentTimeMillis();
3333     List<Put> puts = new ArrayList<>(1);
3334     Put put = new Put(row1);
3335     if (mark == DeleteMark.FAMILY_VERSION) {
3336       put.addColumn(fam, qual, now, value);
3337     } else {
3338       put.addColumn(fam, qual, value);
3339     }
3340 
3341     puts.add(put);
3342     try (Table table = TEST_UTIL.getConnection().getTable(tableName)){
3343       table.put(puts);
3344       Result r = table.get(new Get(row1));
3345       assertEquals(1, r.size());
3346       assertEquals(Bytes.toString(value), Bytes.toString(CellUtil.cloneValue(r.rawCells()[0])));
3347 
3348       Delete d = addDeleteMark(new Delete(row1), mark, now);
3349       table.delete(d);
3350       r = table.get(new Get(row1));
3351       assertEquals(0, r.size());
3352     }
3353   }
3354 
3355   @Test
3356   public void testDeleteCellWithVisibility() throws IOException, InterruptedException {
3357     for (DeleteMark mark : DeleteMark.values()) {
3358       testDeleteCellWithVisibility(mark);
3359       testDeleteCellWithVisibilityV2(mark);
3360     }
3361   }
3362 
3363   private void testDeleteCellWithVisibility(DeleteMark mark) throws IOException, InterruptedException {
3364     setAuths();
3365     final TableName tableName = TableName.valueOf("testDeleteCellWithVisibility-" + mark.name());
3366     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
3367     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
3368     colDesc.setMaxVersions(5);
3369     HTableDescriptor desc = new HTableDescriptor(tableName);
3370     desc.addFamily(colDesc);
3371     hBaseAdmin.createTable(desc);
3372     long now = System.currentTimeMillis();
3373     List<Put> puts = new ArrayList<>(2);
3374     Put put = new Put(row1);
3375     if (mark == DeleteMark.FAMILY_VERSION) {
3376       put.addColumn(fam, qual, now, value);
3377     } else {
3378       put.addColumn(fam, qual, value);
3379     }
3380     puts.add(put);
3381     put = new Put(row1);
3382     if (mark == DeleteMark.FAMILY_VERSION) {
3383       put.addColumn(fam, qual, now, value1);
3384     } else {
3385       put.addColumn(fam, qual, value1);
3386     }
3387     put.setCellVisibility(new CellVisibility(PRIVATE));
3388     puts.add(put);
3389     try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
3390       table.put(puts);
3391       Result r = table.get(new Get(row1));
3392       assertEquals(0, r.size());
3393       r = table.get(new Get(row1).setAuthorizations(new Authorizations(PRIVATE)));
3394       assertEquals(1, r.size());
3395       assertEquals(Bytes.toString(value1), Bytes.toString(CellUtil.cloneValue(r.rawCells()[0])));
3396 
3397       Delete d = addDeleteMark(new Delete(row1), mark, now);
3398       table.delete(d);
3399 
3400       r = table.get(new Get(row1));
3401       assertEquals(0, r.size());
3402       r = table.get(new Get(row1).setAuthorizations(new Authorizations(PRIVATE)));
3403       assertEquals(1, r.size());
3404       assertEquals(Bytes.toString(value1), Bytes.toString(CellUtil.cloneValue(r.rawCells()[0])));
3405 
3406       d = addDeleteMark(new Delete(row1).setCellVisibility(new CellVisibility(PRIVATE)), mark, now);
3407       table.delete(d);
3408 
3409       r = table.get(new Get(row1));
3410       assertEquals(0, r.size());
3411       r = table.get(new Get(row1).setAuthorizations(new Authorizations(PRIVATE)));
3412       assertEquals(0, r.size());
3413     }
3414   }
3415 
3416   private void testDeleteCellWithVisibilityV2(DeleteMark mark) throws IOException, InterruptedException {
3417     setAuths();
3418     final TableName tableName = TableName.valueOf("testDeleteCellWithVisibilityV2-" + mark.name());
3419     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
3420     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
3421     colDesc.setMaxVersions(5);
3422     HTableDescriptor desc = new HTableDescriptor(tableName);
3423     desc.addFamily(colDesc);
3424     hBaseAdmin.createTable(desc);
3425     long now = System.currentTimeMillis();
3426     List<Put> puts = new ArrayList<>(2);
3427     Put put = new Put(row1);
3428     put.setCellVisibility(new CellVisibility(PRIVATE));
3429     if (mark == DeleteMark.FAMILY_VERSION) {
3430       put.addColumn(fam, qual, now, value);
3431     } else {
3432       put.addColumn(fam, qual, value);
3433     }
3434     puts.add(put);
3435     put = new Put(row1);
3436     if (mark == DeleteMark.FAMILY_VERSION) {
3437       put.addColumn(fam, qual, now, value1);
3438     } else {
3439       put.addColumn(fam, qual, value1);
3440     }
3441     puts.add(put);
3442     try (Table table = TEST_UTIL.getConnection().getTable(tableName)){
3443       table.put(puts);
3444       Result r = table.get(new Get(row1));
3445       assertEquals(1, r.size());
3446       assertEquals(Bytes.toString(value1), Bytes.toString(CellUtil.cloneValue(r.rawCells()[0])));
3447       r = table.get(new Get(row1).setAuthorizations(new Authorizations(PRIVATE)));
3448       assertEquals(1, r.size());
3449       assertEquals(Bytes.toString(value1), Bytes.toString(CellUtil.cloneValue(r.rawCells()[0])));
3450 
3451       Delete d = addDeleteMark(new Delete(row1), mark, now);
3452       table.delete(d);
3453 
3454       r = table.get(new Get(row1));
3455       assertEquals(0, r.size());
3456       r = table.get(new Get(row1).setAuthorizations(new Authorizations(PRIVATE)));
3457       assertEquals(0, r.size());
3458 
3459       d = addDeleteMark(new Delete(row1).setCellVisibility(new CellVisibility(PRIVATE)), mark, now);
3460       table.delete(d);
3461 
3462       r = table.get(new Get(row1));
3463       assertEquals(0, r.size());
3464       r = table.get(new Get(row1).setAuthorizations(new Authorizations(PRIVATE)));
3465       assertEquals(0, r.size());
3466     }
3467   }
3468 }