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