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