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