From 6c896ee4958446bb0192b647385eb2449557d465 Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Mon, 14 Apr 2025 11:52:02 -0400 Subject: [PATCH 01/10] Comprehensive table operations IT Creates a comprehensive IT of all table operations against both system and user tables while trying to avoid duplicating existing testing. For example, when there was more extensive testing of a table operation elsewhere, these new tests just ensure that that testing still exists. This IT does not test for edge cases, but rather tests for basic expected functionality of all table operations against user tables and all system tables (ROOT, METADATA, FATE, SCAN_REF). --- .../clientImpl/ClientTabletCacheImpl.java | 1 + .../test/ComprehensiveTableOperationsIT.java | 957 ++++++++++++++++++ .../apache/accumulo/test/ImportExportIT.java | 44 +- .../org/apache/accumulo/test/MetaSplitIT.java | 3 +- .../org/apache/accumulo/test/SampleIT.java | 2 +- .../accumulo/test/functional/BulkNewIT.java | 6 +- .../accumulo/test/functional/CloneTestIT.java | 24 +- .../test/functional/LocalityGroupIT.java | 19 +- 8 files changed, 1009 insertions(+), 47 deletions(-) create mode 100644 test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java diff --git a/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientTabletCacheImpl.java b/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientTabletCacheImpl.java index 5962c23e985..4fd3ed42d11 100644 --- a/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientTabletCacheImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientTabletCacheImpl.java @@ -660,6 +660,7 @@ private void requestTabletHosting(ClientContext context, } // System tables should always be hosted + // TODO should this return for all sys tables? if (AccumuloTable.ROOT.tableId() == tableId || AccumuloTable.METADATA.tableId() == tableId) { return; } diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java new file mode 100644 index 00000000000..414d2662c40 --- /dev/null +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java @@ -0,0 +1,957 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.accumulo.test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.Method; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.accumulo.core.Constants; +import org.apache.accumulo.core.client.Accumulo; +import org.apache.accumulo.core.client.AccumuloClient; +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.IteratorSetting; +import org.apache.accumulo.core.client.admin.TableOperations; +import org.apache.accumulo.core.client.admin.TabletAvailability; +import org.apache.accumulo.core.client.admin.TimeType; +import org.apache.accumulo.core.client.summary.SummarizerConfiguration; +import org.apache.accumulo.core.clientImpl.ClientContext; +import org.apache.accumulo.core.conf.Property; +import org.apache.accumulo.core.data.Key; +import org.apache.accumulo.core.data.Mutation; +import org.apache.accumulo.core.data.Range; +import org.apache.accumulo.core.data.TableId; +import org.apache.accumulo.core.data.Value; +import org.apache.accumulo.core.iterators.Filter; +import org.apache.accumulo.core.iterators.IteratorUtil; +import org.apache.accumulo.core.iterators.SortedKeyValueIterator; +import org.apache.accumulo.core.iterators.user.VersioningIterator; +import org.apache.accumulo.core.metadata.AccumuloTable; +import org.apache.accumulo.core.metadata.ScanServerRefTabletFile; +import org.apache.accumulo.core.metadata.StoredTabletFile; +import org.apache.accumulo.core.metadata.schema.TabletsMetadata; +import org.apache.accumulo.core.security.Authorizations; +import org.apache.accumulo.harness.SharedMiniClusterBase; +import org.apache.accumulo.minicluster.ServerType; +import org.apache.accumulo.test.functional.BasicSummarizer; +import org.apache.accumulo.test.functional.BulkNewIT; +import org.apache.accumulo.test.functional.CloneTestIT; +import org.apache.accumulo.test.functional.CompactionIT; +import org.apache.accumulo.test.functional.ConstraintIT; +import org.apache.accumulo.test.functional.DeleteRowsIT; +import org.apache.accumulo.test.functional.LocalityGroupIT; +import org.apache.accumulo.test.functional.ManagerAssignmentIT; +import org.apache.accumulo.test.functional.MergeTabletsIT; +import org.apache.accumulo.test.functional.ReadWriteIT; +import org.apache.accumulo.test.functional.RenameIT; +import org.apache.accumulo.test.functional.SlowIterator; +import org.apache.accumulo.test.functional.SummaryIT; +import org.apache.accumulo.test.functional.TabletAvailabilityIT; +import org.apache.accumulo.test.util.Wait; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.Text; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; +import com.google.common.net.HostAndPort; + +/** + * A comprehensive IT of all table operations against user tables and all system tables while + * avoiding duplicating existing testing. This does not test for edge cases, but rather tests for + * basic expected functionality of all table operations against user tables and all system tables. + */ +public class ComprehensiveTableOperationsIT extends SharedMiniClusterBase { + private static final Logger log = LoggerFactory.getLogger(ComprehensiveTableOperationsIT.class); + private static final String SLOW_ITER_NAME = "CustomSlowIter"; + private AccumuloClient client; + private TableOperations ops; + private String userTable; + + @Override + protected Duration defaultTimeout() { + return Duration.ofMinutes(1); + } + + @BeforeAll + public static void setup() throws Exception { + SharedMiniClusterBase.startMiniCluster(); + } + + @AfterAll + public static void teardown() { + SharedMiniClusterBase.stopMiniCluster(); + } + + @BeforeEach + public void beforeEach() { + client = Accumulo.newClient().from(getClientProps()).build(); + ops = client.tableOperations(); + } + + @AfterEach + public void afterEach() throws Exception { + // ensure none of the FATE or SCAN_REF data we created persists between tests. Also ensure the + // user table does not persist between tests + if (userTable != null && ops.exists(userTable)) { + cleanupFateTable(); + ops.delete(userTable); + } + cleanupScanRefTable(); + client.close(); + } + + @Test + public void testAllTested() { + var allTableOps = Arrays.stream(TableOperations.class.getDeclaredMethods()).map(Method::getName) + .collect(Collectors.toSet()); + var testMethodNames = Arrays.stream(ComprehensiveTableOperationsIT.class.getDeclaredMethods()) + .map(Method::getName).collect(Collectors.toSet()); + var allTableOpsIter = allTableOps.iterator(); + while (allTableOpsIter.hasNext()) { + var tableOp = allTableOpsIter.next(); + for (var testMethodName : testMethodNames) { + if (testMethodName.contains(tableOp)) { + allTableOpsIter.remove(); + break; + } + } + } + assertTrue(allTableOps.isEmpty(), "The table operations " + allTableOps + " are untested"); + } + + @Test + public void testExpectedSystemTables() { + var testedSystemTableIds = + Set.of(AccumuloTable.ROOT.tableId(), AccumuloTable.METADATA.tableId(), + AccumuloTable.FATE.tableId(), AccumuloTable.SCAN_REF.tableId()); + assertEquals(testedSystemTableIds, AccumuloTable.allTableIds(), + "There are newly added system tables that are untested in this IT. Ensure each " + + "test has testing for the new system table"); + } + + @Test + public void test_list_tableIdMap() throws Exception { + // Thoroughly tested elsewhere, but simple enough to test here. Test that all system tables + // and user tables are returned + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + var expected = Arrays.stream(AccumuloTable.values()).map(AccumuloTable::tableName) + .collect(Collectors.toSet()); + expected.add(userTable); + assertEquals(expected, ops.list()); + assertEquals(expected, ops.tableIdMap().keySet()); + } + + @Test + public void test_exists() throws Exception { + // Thoroughly tested elsewhere, but simple enough to test here. Test that all system tables + // and user tables exist + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + var expected = Arrays.stream(AccumuloTable.values()).map(AccumuloTable::tableName) + .collect(Collectors.toSet()); + expected.add(userTable); + for (String table : expected) { + assertTrue(ops.exists(table)); + } + } + + @Test + public void test_create() throws Exception { + // Creating user tables is thoroughly tested. Make sure we can't create any of the already + // existing system tables, though. + for (var systemTable : AccumuloTable.values()) { + assertThrows(AccumuloException.class, () -> ops.create(systemTable.tableName())); + } + } + + @Test + public void test_exportTable_importTable() throws Exception { + // exportTable, importTable for user tables is tested in ImportExportIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(ImportExportIT.class.getName())); + // exportTable, importTable untested for system tables. Test basic functionality here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + Path baseDir = ImportExportIT.createBaseDir(getCluster(), getClass()); + var fs = getCluster().getFileSystem(); + + // export the user table, so we can test importing into the system tables + ops.offline(userTable, true); + Path exportUserDir; + exportUserDir = new Path(baseDir, "export_userdir"); + fs.deleteOnExit(exportUserDir); + ops.exportTable(userTable, exportUserDir.toString()); + + var sysTables = AccumuloTable.values(); + for (int i = 0; i < sysTables.length; i++) { + var sysTable = sysTables[i]; + Path exportDir = new Path(baseDir, "export" + i); + fs.deleteOnExit(exportDir); + + // not offline, can't export + assertThrows(IllegalStateException.class, + () -> ops.exportTable(sysTable.tableName(), exportDir.toString())); + + switch (sysTable) { + case ROOT: + case METADATA: + // can't offline, so will never be able to export + assertThrows(AccumuloException.class, () -> ops.offline(sysTable.tableName(), true)); + assertThrows(AccumuloException.class, + () -> ops.importTable(sysTable.tableName(), exportUserDir.toString())); + break; + case FATE: + case SCAN_REF: + ops.offline(sysTable.tableName(), true); + try { + assertThrows(AccumuloException.class, + () -> ops.exportTable(sysTable.tableName(), exportDir.toString())); + assertThrows(AccumuloException.class, + () -> ops.importTable(sysTable.tableName(), exportUserDir.toString())); + } finally { + ops.online(sysTable.tableName(), true); + } + break; + default: + throw new IllegalStateException("Unrecognized table: " + sysTable); + } + } + } + + @Test + public void test_addSplits_putSplits_listSplits_splitRangeByTablets() throws Exception { + // note that addSplits and putSplits are implemented the same, just take different args. No + // need to test both + + // addSplits, listSplits tested elsewhere for METADATA, ROOT, and user tables, but testing here + // as well since this setup is needed to test for splitRangeByTablets anyway, which is untested + // elsewhere + + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + // system and user tables + var allTables = new ArrayList<>(ops.list()); + + for (int i = 0; i < allTables.size(); i++) { + SortedSet splits = new TreeSet<>(); + splits.add(new Text(i + "")); + String table = allTables.get(i); + + if (table.equals(AccumuloTable.ROOT.tableName())) { + // cannot add splits to ROOT + assertThrows(AccumuloException.class, () -> ops.addSplits(table, splits)); + assertEquals(0, ops.listSplits(table).size()); + } else { + ops.addSplits(table, splits); + assertTrue(ops.listSplits(table).containsAll(splits)); + } + + assertEquals(ops.splitRangeByTablets(table, new Range(), 99).size(), + ops.listSplits(table).size() + 1); + } + } + + @Test + public void test_locate() throws Exception { + // locate for user tables is tested in LocatorIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(LocatorIT.class.getName())); + // locate for METADATA and ROOT tables is tested in ManagerAssignmentIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(ManagerAssignmentIT.class.getName())); + + // basic functionality check for locate on FATE and SCAN_REF tables + var fateLocations = + ops.locate(AccumuloTable.FATE.tableName(), Collections.singletonList(new Range())); + var fateGroupByTablet = fateLocations.groupByTablet().keySet(); + assertFalse(fateGroupByTablet.isEmpty()); + fateGroupByTablet.forEach(tid -> { + var tabletLoc = fateLocations.getTabletLocation(tid); + assertNotNull(tabletLoc); + assertTrue(tabletLoc.contains(":")); + }); + var scanRefLocations = + ops.locate(AccumuloTable.SCAN_REF.tableName(), Collections.singletonList(new Range())); + var scanRefGroupByTablet = scanRefLocations.groupByTablet().keySet(); + assertFalse(scanRefGroupByTablet.isEmpty()); + scanRefGroupByTablet.forEach(tid -> { + var tabletLoc = scanRefLocations.getTabletLocation(tid); + assertNotNull(tabletLoc); + assertTrue(tabletLoc.contains(":")); + }); + } + + @Test + public void test_getMaxRow_deleteRows() throws Exception { + // getMaxRow for user tables is tested in FindMaxIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(FindMaxIT.class.getName())); + // getMaxRow not tested for system tables. Test basic functionality here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + createFateTableRow(userTable); + createScanRefTableRow(); + for (var sysTable : AccumuloTable.values()) { + var maxRow = + ops.getMaxRow(sysTable.tableName(), Authorizations.EMPTY, null, true, null, true); + log.info("Max row of {} : {}", sysTable, maxRow); + assertNotNull(maxRow); + } + + // deleteRows for user tables is tested in DeleteRowsIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(DeleteRowsIT.class.getName())); + // deleteRows not tested for system tables. Test basic functionality here + for (var sysTable : AccumuloTable.values()) { + switch (sysTable) { + case METADATA: + case ROOT: + // should not be able to delete rows of METADATA or ROOT tables + assertThrows(AccumuloException.class, + () -> ops.deleteRows(sysTable.tableName(), null, null)); + break; + case FATE: + break; + case SCAN_REF: + cleanupScanRefTable(); + // check max row again + assertNull( + ops.getMaxRow(sysTable.tableName(), Authorizations.EMPTY, null, true, null, true)); + break; + default: + throw new IllegalStateException("Unrecognized table: " + sysTable); + } + } + } + + @Test + public void test_merge() throws Exception { + // merge for user tables is tested in various ITs. One example is MergeTabletsIT. Ensure + // test exists + assertDoesNotThrow(() -> Class.forName(MergeTabletsIT.class.getName())); + // merge for METADATA and ROOT system tables tested in MetaSplitIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(MetaSplitIT.class.getName())); + // merge for FATE and SCAN_REF tables not tested. Test basic functionality here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + var fateRow1 = createFateTableRow(userTable); + createFateTableRow(userTable); // fate row 2 + var scanRefRow1 = createScanRefTableRow(); + createScanRefTableRow(); // scan ref row 2 + + SortedSet fateSplits = new TreeSet<>(); + fateSplits.add(new Text(fateRow1)); + ops.addSplits(AccumuloTable.FATE.tableName(), fateSplits); + // there may be preexisting splits on the FATE table from a previous test + assertTrue(ops.listSplits(AccumuloTable.FATE.tableName()).contains(fateRow1)); + ops.merge(AccumuloTable.FATE.tableName(), null, null); + assertTrue(ops.listSplits(AccumuloTable.FATE.tableName()).isEmpty()); + + SortedSet scanRefSplits = new TreeSet<>(); + scanRefSplits.add(new Text(scanRefRow1)); + ops.addSplits(AccumuloTable.SCAN_REF.tableName(), scanRefSplits); + // there may be preexisting splits on the SCAN_REF table from a previous test + assertTrue(ops.listSplits(AccumuloTable.SCAN_REF.tableName()).contains(scanRefRow1)); + ops.merge(AccumuloTable.SCAN_REF.tableName(), null, null); + assertTrue(ops.listSplits(AccumuloTable.SCAN_REF.tableName()).isEmpty()); + } + + @Test + public void test_compact() throws Exception { + // compact for user tables is tested in various ITs. One example is CompactionIT. Ensure + // test exists + assertDoesNotThrow(() -> Class.forName(CompactionIT.class.getName())); + // disable the GC to prevent automatic compactions on METADATA and ROOT tables + getCluster().getClusterControl().stopAllServers(ServerType.GARBAGE_COLLECTOR); + try { + // test basic functionality for system tables + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + + // create some RFiles for the METADATA and ROOT tables by creating some data in the user + // table, flushing that table, then the METADATA table, then the ROOT table + for (int i = 0; i < 3; i++) { + try (var bw = client.createBatchWriter(userTable)) { + var mut = new Mutation("r" + i); + mut.put("cf", "cq", "v"); + bw.addMutation(mut); + } + ops.flush(userTable, null, null, true); + ops.flush(AccumuloTable.METADATA.tableName(), null, null, true); + ops.flush(AccumuloTable.ROOT.tableName(), null, null, true); + } + + for (var sysTable : List.of(AccumuloTable.ROOT, AccumuloTable.METADATA, + AccumuloTable.SCAN_REF, AccumuloTable.FATE)) { + // create some RFiles for FATE and SCAN_REF tables + if (sysTable == AccumuloTable.SCAN_REF) { + createScanRefTableRow(); + ops.flush(AccumuloTable.SCAN_REF.tableName(), null, null, true); + } else if (sysTable == AccumuloTable.FATE) { + createFateTableRow(userTable); + ops.flush(AccumuloTable.FATE.tableName(), null, null, true); + } + + Set stfsBeforeCompact = getStoredTabFiles(sysTable); + + log.info("Compacting " + sysTable); + ops.compact(sysTable.tableName(), null, null, true, true); + log.info("Finished compacting " + sysTable); + + // RFiles resulting from a compaction begin with 'A'. Wait until we see an RFile beginning + // with 'A' that was not present before the compaction. + Wait.waitFor(() -> { + var stfsAfterCompact = getStoredTabFiles(sysTable); + String regex = "^A.*\\.rf$"; + var A_stfsBeforeCompaction = stfsBeforeCompact.stream() + .filter(stf -> stf.getFileName().matches(regex)).collect(Collectors.toSet()); + var A_stfsAfterCompaction = stfsAfterCompact.stream() + .filter(stf -> stf.getFileName().matches(regex)).collect(Collectors.toSet()); + return !Sets.difference(A_stfsAfterCompaction, A_stfsBeforeCompaction).isEmpty(); + }); + } + } finally { + getCluster().getClusterControl().startAllServers(ServerType.GARBAGE_COLLECTOR); + } + } + + @Test + public void test_cancelCompaction() throws Exception { + // cancelCompaction for user tables is tested in various ITs. One example is TableOperationsIT. + // Ensure test exists + assertDoesNotThrow(() -> Class.forName(TableOperationsIT.class.getName())); + // test basic functionality for system tables + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + + // Need some data in all the system tables. This allows the slow iterator we attach to the + // system table to work when we compact. ROOT and METADATA will already have data, so just need + // to create some data for the other system tables + createFateTableRow(userTable); + createScanRefTableRow(); + + for (var sysTable : AccumuloTable.values()) { + try { + var zrw = getCluster().getServerContext().getZooSession().asReaderWriter(); + attachSlowMajcIterator(sysTable.tableName()); + + var metaFatesBeforeCompact = new HashSet<>(zrw.getChildren(Constants.ZFATE)); + + log.info("Compacting " + sysTable); + ops.compact(sysTable.tableName(), null, null, true, false); + log.info("Initiated compaction for " + sysTable); + + // Wait for the compaction to be started + Wait.waitFor(() -> { + var metaFatesAfterCompact = new HashSet<>(zrw.getChildren(Constants.ZFATE)); + return !Sets.difference(metaFatesAfterCompact, metaFatesBeforeCompact).isEmpty(); + }); + + log.info("Cancelling compaction " + sysTable); + ops.cancelCompaction(sysTable.tableName()); + + // We can be sure that the compaction has been cancelled once we see no FATE operations + Wait.waitFor(() -> { + Set metaFatesAfterCancelCompact = new HashSet<>(zrw.getChildren(Constants.ZFATE)); + return metaFatesAfterCancelCompact.isEmpty(); + }); + } finally { + removeSlowMajcIterator(sysTable.tableName()); + } + } + } + + @Test + public void test_delete() throws Exception { + // delete for user tables is tested in TableOperationsIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(TableOperationsIT.class.getName())); + // delete not tested for system tables. Test basic functionality here + for (var sysTable : AccumuloTable.values()) { + assertThrows(AccumuloException.class, () -> ops.delete(sysTable.tableName())); + } + } + + @Test + public void test_clone() throws Exception { + // cloning user and system tables is tested in CloneTestIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(CloneTestIT.class.getName())); + } + + @Test + public void test_rename() throws Exception { + // rename for user tables is tested in RenameIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(RenameIT.class.getName())); + // rename not tested for system tables. Test basic functionality here + var sysTables = AccumuloTable.values(); + var tableNames = getUniqueNames(sysTables.length); + + for (int i = 0; i < sysTables.length; i++) { + var sysTable = sysTables[i]; + var tableName = tableNames[i]; + assertThrows(AccumuloException.class, + () -> client.tableOperations().rename(sysTable.tableName(), tableName)); + } + } + + @Test + public void test_flush() throws Exception { + // flush for user tables and the METADATA and ROOT tables is tested in CompactionIT. Ensure + // test exists + assertDoesNotThrow(() -> Class.forName(CompactionIT.class.getName())); + // flush for FATE and SCAN_REF not tested for. Test basic functionality here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + createFateTableRow(userTable); + createScanRefTableRow(); + + for (var sysTable : Set.of(AccumuloTable.FATE, AccumuloTable.SCAN_REF)) { + int numFilesBeforeFlush = 0; + + try (TabletsMetadata tabletsMetadata = getCluster().getServerContext().getAmple() + .readTablets().forTable(sysTable.tableId()).build()) { + for (var tm : tabletsMetadata) { + numFilesBeforeFlush += tm.getFiles().size(); + } + } + ops.flush(sysTable.tableName(), null, null, true); + // Wait until we see the new file + final int finalNumFilesBeforeFlush = numFilesBeforeFlush; + Wait.waitFor(() -> { + try (TabletsMetadata tabletsMetadata = getCluster().getServerContext().getAmple() + .readTablets().forTable(sysTable.tableId()).build()) { + int numFilesAfterFlush = 0; + for (var tm : tabletsMetadata) { + numFilesAfterFlush += tm.getFiles().size(); + } + return numFilesAfterFlush > finalNumFilesBeforeFlush; + } + }); + } + } + + @Test + public void + test_setProperty_modifyProperties_removeProperty_getProperties_getTableProperties_getConfiguration() + throws Exception { + // These may be tested elsewhere across several tests, but simpler to test all here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + // system and user tables + Set allTables = ops.list(); + for (String tableName : allTables) { + // setProperty + String propKey = Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "prop"; + String propVal = "val"; + String newPropVal = "newval"; + ops.setProperty(tableName, propKey, propVal); + // getProperties, getTableProperties, and getConfiguration + assertTrue(propFound(tableName, propKey, propVal)); + assertEquals(propVal, ops.getTableProperties(tableName).get(propKey)); + assertEquals(propVal, ops.getConfiguration(tableName).get(propKey)); + // modifyProperties + ops.modifyProperties(tableName, properties -> properties.put(propKey, newPropVal)); + // getProperties, getTableProperties, and getConfiguration + assertTrue(propFound(tableName, propKey, newPropVal)); + assertEquals(newPropVal, ops.getTableProperties(tableName).get(propKey)); + assertEquals(newPropVal, ops.getConfiguration(tableName).get(propKey)); + // removeProperty + ops.removeProperty(tableName, propKey); + // getProperties, getTableProperties, and getConfiguration + assertFalse(propFound(tableName, propKey, newPropVal)); + assertNull(ops.getTableProperties(tableName).get(propKey)); + assertNull(ops.getConfiguration(tableName).get(propKey)); + } + } + + @Test + public void test_setLocalityGroups_getLocalityGroups() throws Exception { + // setLocalityGroups, getLocalityGroups for user tables is tested in LocalityGroupIT. Ensure + // test exists + assertDoesNotThrow(() -> Class.forName(LocalityGroupIT.class.getName())); + // setLocalityGroups, getLocalityGroups for system tables not tested for. Test basic + // functionality here + for (var sysTable : AccumuloTable.values()) { + LocalityGroupIT.createAndSetLocalityGroups(client, sysTable.tableName()); + LocalityGroupIT.verifyLocalityGroupSet(client, sysTable.tableName()); + } + } + + @Test + public void test_importDirectory() throws Exception { + // importDirectory for user tables is tested in BulkNewIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(BulkNewIT.class.getName())); + // importDirectory for system tables not tested for. Test basic functionality here + var rootPath = getCluster().getTemporaryPath().toString(); + var dir = rootPath + "/" + getUniqueNames(1)[0]; + BulkNewIT.writeData(dir + "/f1.", getCluster().getServerContext().getConfiguration(), 0, 5, 0); + + for (var sysTable : AccumuloTable.values()) { + assertThrows(Exception.class, () -> ops.importDirectory(dir).to(sysTable.tableName()).load()); + } + } + + @Test + public void test_offline_online_isOnline() throws Exception { + // offline,online,isOnline for user tables is tested in ComprehensiveBaseIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(ComprehensiveBaseIT.class.getName())); + // offline,online,isOnline not tested for system tables. Test basic functionality here + for (var sysTable : AccumuloTable.values()) { + switch (sysTable) { + case ROOT: + case METADATA: + assertTrue(client.tableOperations().isOnline(sysTable.tableName())); + assertThrows(AccumuloException.class, + () -> client.tableOperations().offline(sysTable.tableName(), true)); + assertTrue(client.tableOperations().isOnline(sysTable.tableName())); + client.tableOperations().online(sysTable.tableName(), true); + break; + case SCAN_REF: + case FATE: + assertTrue(client.tableOperations().isOnline(sysTable.tableName())); + client.tableOperations().offline(sysTable.tableName(), true); + assertFalse(client.tableOperations().isOnline(sysTable.tableName())); + client.tableOperations().online(sysTable.tableName(), true); + assertTrue(client.tableOperations().isOnline(sysTable.tableName())); + break; + default: + throw new IllegalStateException("Unrecognized table: " + sysTable); + } + } + } + + @Test + public void test_clearLocatorCache() throws Exception { + // clearLocatorCache is tested elsewhere for user tables but not for system tables. Simple + // enough to test all tables here + var clientContext = (ClientContext) client; + userTable = getUniqueNames(1)[0]; + + client.tableOperations().create(userTable); + ReadWriteIT.ingest(clientContext, 5, 5, 5, 0, userTable); + assertTrue(clientContext.getTabletLocationCache(TableId.of(ops.tableIdMap().get(userTable))) + .getTabletHostingRequestCount() > 0); + ops.clearLocatorCache(userTable); + assertEquals(0, + clientContext.getTabletLocationCache(TableId.of(ops.tableIdMap().get(userTable))) + .getTabletHostingRequestCount()); + + for (var sysTable : AccumuloTable.values()) { + assertEquals(0, + clientContext.getTabletLocationCache(sysTable.tableId()).getTabletHostingRequestCount()); + ops.clearLocatorCache(sysTable.tableName()); + assertEquals(0, + clientContext.getTabletLocationCache(sysTable.tableId()).getTabletHostingRequestCount()); + } + } + + @Test + public void + test_attachIterator_removeIterator_getIteratorSetting_listIterators_checkIteratorConflicts() + throws Exception { + // These may be tested elsewhere across several tests, but simpler to test all here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + String iterName = "iter_name"; + var iterSetting = new IteratorSetting(100, iterName, NoOpFilter.class); + var scope = EnumSet.of(IteratorUtil.IteratorScope.majc, IteratorUtil.IteratorScope.minc); + // system and user tables + Set allTables = ops.list(); + + for (String table : allTables) { + ops.attachIterator(table, iterSetting, scope); + try { + assertTrue(ops.listIterators(table).containsKey(iterName)); + assertNull(ops.getIteratorSetting(table, iterName, IteratorUtil.IteratorScope.scan)); + assertEquals(iterSetting, + ops.getIteratorSetting(table, iterName, IteratorUtil.IteratorScope.majc)); + assertThrows(AccumuloException.class, + () -> ops.checkIteratorConflicts(table, iterSetting, scope)); + ops.checkIteratorConflicts(table, iterSetting, EnumSet.of(IteratorUtil.IteratorScope.scan)); + } finally { + ops.removeIterator(table, iterName, scope); + assertFalse(ops.listIterators(table).containsKey(iterName)); + } + } + } + + @Test + public void test_addConstraint_listConstraints_removeConstraint() throws Exception { + // addConstraint, listConstraints, removeConstraint for user tables is tested in ConstraintIT. + // Ensure test exists + assertDoesNotThrow(() -> Class.forName(ConstraintIT.class.getName())); + // addConstraint, listConstraints, removeConstraint not tested for system tables. Test basic + // functionality here + for (var sysTable : AccumuloTable.values()) { + var numExistingConstraints = ops.listConstraints(sysTable.tableName()).size(); + String constraint = ComprehensiveBaseIT.TestConstraint.class.getName(); + + var constraintNum = ops.addConstraint(sysTable.tableName(), constraint); + + var listConstraints = ops.listConstraints(sysTable.tableName()); + assertEquals(numExistingConstraints + 1, listConstraints.size()); + assertEquals(constraintNum, listConstraints.get(constraint)); + + ops.removeConstraint(sysTable.tableName(), constraintNum); + + listConstraints = ops.listConstraints(sysTable.tableName()); + assertEquals(numExistingConstraints, listConstraints.size()); + assertNull(listConstraints.get(constraint)); + } + } + + @Test + public void test_getDiskUsage() throws Exception { + // getDiskUsage for user tables is tested in TableOperationsIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(TableOperationsIT.class.getName())); + // getDiskUsage not tested for system tables. Test basic functionality here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + createFateTableRow(userTable); + createScanRefTableRow(); + for (var sysTable : AccumuloTable.values()) { + ops.flush(sysTable.tableName(), null, null, true); + var diskUsageList = ops.getDiskUsage(Set.of(sysTable.tableName())); + assertEquals(1, diskUsageList.size()); + var diskUsage = diskUsageList.get(0); + log.info("table : {}, disk usage : {}", sysTable.tableName(), diskUsage.getUsage()); + if (!sysTable.equals(AccumuloTable.ROOT)) { + assertTrue(diskUsage.getUsage() > 0); + } + } + } + + @Test + public void test_testClassLoad() throws Exception { + // testClassLoad is untested. Test basic functionality here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + // system and user tables + Set allTables = ops.list(); + for (var table : allTables) { + // VersioningIterator is a default iterator + assertTrue(ops.testClassLoad(table, VersioningIterator.class.getName(), + SortedKeyValueIterator.class.getName())); + assertFalse(ops.testClassLoad(table, "foo", SortedKeyValueIterator.class.getName())); + } + } + + @Test + public void test_setSamplerConfiguration_getSamplerConfiguration_clearSamplerConfiguration() + throws Exception { + // these are mostly untested. Test basic functionality here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + // system and user tables + Set allTables = ops.list(); + for (var table : allTables) { + ops.setSamplerConfiguration(table, SampleIT.SC1); + assertEquals(SampleIT.SC1, ops.getSamplerConfiguration(table)); + ops.clearSamplerConfiguration(table); + assertNull(ops.getSamplerConfiguration(table)); + } + } + + @Test + public void test_summaries_addSummarizers_removeSummarizers_listSummarizers() throws Exception { + // these are all tested for user tables in SummaryIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(SummaryIT.class.getName())); + // these are not tested for system tables. Test basic functionality here + for (var sysTable : AccumuloTable.values()) { + SummarizerConfiguration sc = SummarizerConfiguration.builder(BasicSummarizer.class).build(); + + assertThrows(AccumuloSecurityException.class, + () -> ops.summaries(sysTable.tableName()).retrieve()); + ops.addSummarizers(sysTable.tableName(), sc); + assertEquals(List.of(sc), ops.listSummarizers(sysTable.tableName())); + ops.removeSummarizers(sysTable.tableName(), sc1 -> true); + assertTrue(ops.listSummarizers(sysTable.tableName()).isEmpty()); + } + } + + @Test + public void test_getTimeType() throws Exception { + // getTimeType is tested elsewhere but not for all system tables. Simple enough to test all + // tables here + userTable = getUniqueNames(1)[0]; + ops.create(userTable); + + assertEquals(TimeType.MILLIS, ops.getTimeType(userTable)); + for (var sysTable : AccumuloTable.values()) { + assertEquals(TimeType.LOGICAL, ops.getTimeType(sysTable.tableName())); + } + } + + @Test + public void test_setTabletAvailability_getTabletInformation() throws Exception { + // these are tested for user tables in TabletAvailabilityIT. Ensure test exists + assertDoesNotThrow(() -> Class.forName(TabletAvailabilityIT.class.getName())); + // these are not tested for system tables. Test basic functionality here + for (var sysTable : AccumuloTable.values()) { + // should not be able to unhost any system table + assertThrows(IllegalArgumentException.class, () -> ops + .setTabletAvailability(sysTable.tableName(), new Range(), TabletAvailability.UNHOSTED)); + assertTrue(ops.getTabletInformation(sysTable.tableName(), new Range()).findAny().isPresent()); + ops.getTabletInformation(sysTable.tableName(), new Range()) + .forEach(ti -> assertEquals(TabletAvailability.HOSTED, ti.getTabletAvailability())); + } + } + + /** + * Creates some data in the FATE table. Will create a single row each call. Does so by initiating + * a very slow compaction on the given table. + * + * @param table the table the fate operation will operate on + * @return the row created + */ + private Text createFateTableRow(String table) throws Exception { + attachSlowMajcIterator(table); + ReadWriteIT.ingest(client, 5, 5, 5, 0, table); + + Set rowsSeenBeforeNewOp = new HashSet<>(); + try (var scanner = client.createScanner(AccumuloTable.FATE.tableName())) { + for (var entry : scanner) { + rowsSeenBeforeNewOp.add(entry.getKey().getRow()); + } + } + + // start a very slow compaction to create a FATE op that will linger in the FATE table until + // cancelled + client.tableOperations().compact(table, null, null, true, false); + + Set rowsSeenAfterNewOp = new HashSet<>(); + try (var scanner = client.createScanner(AccumuloTable.FATE.tableName())) { + for (var entry : scanner) { + rowsSeenAfterNewOp.add(entry.getKey().getRow()); + } + } + + var newOp = Sets.difference(rowsSeenAfterNewOp, rowsSeenBeforeNewOp); + assertEquals(1, newOp.size()); + return newOp.stream().findFirst().orElseThrow(); + } + + private void attachSlowMajcIterator(String table) throws Exception { + if (!ops.listIterators(table).containsKey(SLOW_ITER_NAME)) { + IteratorSetting is = new IteratorSetting(1, SLOW_ITER_NAME, SlowIterator.class); + is.addOption("sleepTime", "60000"); + ops.attachIterator(table, is, EnumSet.of(IteratorUtil.IteratorScope.majc)); + } + } + + private void removeSlowMajcIterator(String table) throws Exception { + ops.removeIterator(table, SLOW_ITER_NAME, EnumSet.of(IteratorUtil.IteratorScope.majc)); + } + + /** + * Creates some data in the SCAN_REF table. Will create a single row each call. + * + * @return the row created + */ + private Text createScanRefTableRow() { + HostAndPort server = HostAndPort.fromParts("127.0.0.1", 1234); + UUID serverLockUUID = UUID.randomUUID(); + Set scanRefs = Stream.of("F0000070.rf", "F0000071.rf") + .map(f -> "hdfs://localhost:8020/accumulo/tables/2a/default_tablet/" + f) + .map(f -> new ScanServerRefTabletFile(f, server.toString(), serverLockUUID)) + .collect(Collectors.toSet()); + getCluster().getServerContext().getAmple().scanServerRefs().put(scanRefs); + return new Text(getCluster().getServerContext().getAmple().scanServerRefs().list() + .filter(tf -> tf.getServerLockUUID().equals(serverLockUUID)).findFirst().orElseThrow() + .getServerLockUUID().toString()); + } + + /** + * Cleans up the data in the FATE table that was created by calls to + * {@link #createFateTableRow(String)} + */ + private void cleanupFateTable() throws Exception { + ops.cancelCompaction(userTable); + // Wait for FATE table to be clear + Wait.waitFor(() -> { + try (var scanner = client.createScanner(AccumuloTable.FATE.tableName())) { + return !scanner.iterator().hasNext(); + } + }); + } + + /** + * Cleans up the data in the SCAN_REF table that was created by calls to + * {@link #createScanRefTableRow()} + */ + private void cleanupScanRefTable() throws Exception { + ops.deleteRows(AccumuloTable.SCAN_REF.tableName(), null, null); + } + + private boolean propFound(String tableName, String key, String val) throws Exception { + var propsIter = ops.getProperties(tableName).iterator(); + boolean propFound = false; + while (propsIter.hasNext()) { + var prop = propsIter.next(); + if (prop.getKey().equals(key) && prop.getValue().equals(val)) { + propFound = true; + break; + } + } + return propFound; + } + + private Set getStoredTabFiles(AccumuloTable sysTable) throws Exception { + var clientContext = (ClientContext) client; + Set storedTabFiles = new HashSet<>(); + try (TabletsMetadata tabletsMetadata = + clientContext.getAmple().readTablets().forTable(sysTable.tableId()).build()) { + for (var tm : tabletsMetadata) { + var stfs = tm.getFiles(); + storedTabFiles.addAll(stfs); + stfs.forEach(f -> log.info("Found stored tablet file: {} for the system table: {}", + f.getMetadataPath(), sysTable.tableName())); + } + } + return storedTabFiles; + } + + private static class NoOpFilter extends Filter { + @Override + public boolean accept(Key k, Value v) { + return true; + } + } +} diff --git a/test/src/main/java/org/apache/accumulo/test/ImportExportIT.java b/test/src/main/java/org/apache/accumulo/test/ImportExportIT.java index 7bd7bd5efba..abf0832be2e 100644 --- a/test/src/main/java/org/apache/accumulo/test/ImportExportIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ImportExportIT.java @@ -131,15 +131,7 @@ private void doExportImportThenScan(boolean fenced, AccumuloClient client, Strin // Make a directory we can use to throw the export and import directories // Must exist on the filesystem the cluster is running. FileSystem fs = cluster.getFileSystem(); - log.info("Using FileSystem: " + fs); - Path baseDir = new Path(cluster.getTemporaryPath(), getClass().getName()); - fs.deleteOnExit(baseDir); - if (fs.exists(baseDir)) { - log.info("{} exists on filesystem, deleting", baseDir); - assertTrue(fs.delete(baseDir, true), "Failed to deleted " + baseDir); - } - log.info("Creating {}", baseDir); - assertTrue(fs.mkdirs(baseDir), "Failed to create " + baseDir); + Path baseDir = createBaseDir(cluster, getClass()); Path exportDir = new Path(baseDir, "export"); fs.deleteOnExit(exportDir); Path importDirA = new Path(baseDir, "import-a"); @@ -287,15 +279,7 @@ public void testExportImportOffline(boolean fenced) throws Exception { // Make export and import directories FileSystem fs = cluster.getFileSystem(); - log.info("Using FileSystem: " + fs); - Path baseDir = new Path(cluster.getTemporaryPath(), getClass().getName()); - fs.deleteOnExit(baseDir); - if (fs.exists(baseDir)) { - log.info("{} exists on filesystem, deleting", baseDir); - assertTrue(fs.delete(baseDir, true), "Failed to deleted " + baseDir); - } - log.info("Creating {}", baseDir); - assertTrue(fs.mkdirs(baseDir), "Failed to create " + baseDir); + Path baseDir = createBaseDir(cluster, getClass()); Path exportDir = new Path(baseDir, "export"); fs.deleteOnExit(exportDir); Path importDirA = new Path(baseDir, "import-a"); @@ -456,15 +440,7 @@ public void testImportedTableIsOnDemand() throws Exception { // Make a directory we can use to throw the export and import directories // Must exist on the filesystem the cluster is running. FileSystem fs = cluster.getFileSystem(); - log.info("Using FileSystem: " + fs); - Path baseDir = new Path(cluster.getTemporaryPath(), getClass().getName()); - fs.deleteOnExit(baseDir); - if (fs.exists(baseDir)) { - log.info("{} exists on filesystem, deleting", baseDir); - assertTrue(fs.delete(baseDir, true), "Failed to deleted " + baseDir); - } - log.info("Creating {}", baseDir); - assertTrue(fs.mkdirs(baseDir), "Failed to create " + baseDir); + Path baseDir = createBaseDir(cluster, getClass()); Path exportDir = new Path(baseDir, "export"); fs.deleteOnExit(exportDir); Path importDirA = new Path(baseDir, "import-a"); @@ -637,4 +613,18 @@ private Set createRanges() { new Range("row_" + String.format("%010d", 699), false, "row_" + String.format("%010d", 749), true)); } + + public static Path createBaseDir(AccumuloCluster cluster, Class clazz) throws IOException { + FileSystem fs = cluster.getFileSystem(); + log.info("Using FileSystem: " + fs); + Path baseDir = new Path(cluster.getTemporaryPath(), clazz.getName()); + fs.deleteOnExit(baseDir); + if (fs.exists(baseDir)) { + log.info("{} exists on filesystem, deleting", baseDir); + assertTrue(fs.delete(baseDir, true), "Failed to deleted " + baseDir); + } + log.info("Creating {}", baseDir); + assertTrue(fs.mkdirs(baseDir), "Failed to create " + baseDir); + return baseDir; + } } diff --git a/test/src/main/java/org/apache/accumulo/test/MetaSplitIT.java b/test/src/main/java/org/apache/accumulo/test/MetaSplitIT.java index 885721a5e2f..f51e7b5c9c9 100644 --- a/test/src/main/java/org/apache/accumulo/test/MetaSplitIT.java +++ b/test/src/main/java/org/apache/accumulo/test/MetaSplitIT.java @@ -97,12 +97,13 @@ public void restoreMetadataSplits() throws Exception { } @Test - public void testRootTableSplit() { + public void testRootTableSplit() throws Exception { try (AccumuloClient client = Accumulo.newClient().from(getClientProps()).build()) { SortedSet splits = new TreeSet<>(); splits.add(new Text("5")); assertThrows(AccumuloException.class, () -> client.tableOperations().addSplits(AccumuloTable.ROOT.tableName(), splits)); + assertTrue(client.tableOperations().listSplits(AccumuloTable.ROOT.tableName()).isEmpty()); } } diff --git a/test/src/main/java/org/apache/accumulo/test/SampleIT.java b/test/src/main/java/org/apache/accumulo/test/SampleIT.java index 928ad740f9f..970fe939108 100644 --- a/test/src/main/java/org/apache/accumulo/test/SampleIT.java +++ b/test/src/main/java/org/apache/accumulo/test/SampleIT.java @@ -92,7 +92,7 @@ public static void teardown() { private static final Map OPTIONS_2 = Map.of("hasher", "murmur3_32", "modulus", "997"); - private static final SamplerConfiguration SC1 = + public static final SamplerConfiguration SC1 = new SamplerConfiguration(RowSampler.class.getName()).setOptions(OPTIONS_1); private static final SamplerConfiguration SC2 = new SamplerConfiguration(RowSampler.class.getName()).setOptions(OPTIONS_2); diff --git a/test/src/main/java/org/apache/accumulo/test/functional/BulkNewIT.java b/test/src/main/java/org/apache/accumulo/test/functional/BulkNewIT.java index bc1a2ddbe2c..c8b6bf386cb 100644 --- a/test/src/main/java/org/apache/accumulo/test/functional/BulkNewIT.java +++ b/test/src/main/java/org/apache/accumulo/test/functional/BulkNewIT.java @@ -1271,7 +1271,7 @@ private void verifyMetadata(AccumuloClient client, String tableName, @SuppressFBWarnings(value = {"PATH_TRAVERSAL_IN", "WEAK_MESSAGE_DIGEST_SHA1"}, justification = "path provided by test; sha-1 is okay for test") - private String hash(String filename) { + private static String hash(String filename) { try { byte[] data = Files.readAllBytes(Paths.get(filename.replaceFirst("^file:", ""))); byte[] hash = MessageDigest.getInstance("SHA1").digest(data); @@ -1285,8 +1285,8 @@ private static String row(int r) { return String.format("%04d", r); } - private String writeData(String file, AccumuloConfiguration aconf, int s, int e, int valueOffset) - throws Exception { + public static String writeData(String file, AccumuloConfiguration aconf, int s, int e, + int valueOffset) throws Exception { FileSystem fs = getCluster().getFileSystem(); String filename = file + RFile.EXTENSION; try (FileSKVWriter writer = FileOperations.getInstance().newWriterBuilder() diff --git a/test/src/main/java/org/apache/accumulo/test/functional/CloneTestIT.java b/test/src/main/java/org/apache/accumulo/test/functional/CloneTestIT.java index a586bd4c7ed..9f7773086da 100644 --- a/test/src/main/java/org/apache/accumulo/test/functional/CloneTestIT.java +++ b/test/src/main/java/org/apache/accumulo/test/functional/CloneTestIT.java @@ -19,6 +19,7 @@ package org.apache.accumulo.test.functional; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -42,7 +43,6 @@ import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.client.Accumulo; import org.apache.accumulo.core.client.AccumuloClient; -import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.BatchWriter; import org.apache.accumulo.core.client.Scanner; import org.apache.accumulo.core.client.TableNotFoundException; @@ -352,18 +352,18 @@ public void testCloneWithSplits() throws Exception { } @Test - public void testCloneRootTable() { + public void testCloneSystemTables() { try (AccumuloClient client = Accumulo.newClient().from(getClientProps()).build()) { - assertThrows(AccumuloException.class, () -> client.tableOperations() - .clone(AccumuloTable.ROOT.tableName(), "rc1", CloneConfiguration.empty())); - } - } - - @Test - public void testCloneMetadataTable() { - try (AccumuloClient client = Accumulo.newClient().from(getClientProps()).build()) { - assertThrows(AccumuloException.class, () -> client.tableOperations() - .clone(AccumuloTable.METADATA.tableName(), "mc1", CloneConfiguration.empty())); + var sysTables = AccumuloTable.values(); + var tableNames = getUniqueNames(sysTables.length); + + for (int i = 0; i < sysTables.length; i++) { + var sysTable = sysTables[i]; + var cloneTableName = tableNames[i]; + assertThrows(Exception.class, () -> client.tableOperations().clone(sysTable.tableName(), + cloneTableName, CloneConfiguration.empty())); + assertFalse(client.tableOperations().exists(cloneTableName)); + } } } } diff --git a/test/src/main/java/org/apache/accumulo/test/functional/LocalityGroupIT.java b/test/src/main/java/org/apache/accumulo/test/functional/LocalityGroupIT.java index d0f07d9c962..031c3aeb48d 100644 --- a/test/src/main/java/org/apache/accumulo/test/functional/LocalityGroupIT.java +++ b/test/src/main/java/org/apache/accumulo/test/functional/LocalityGroupIT.java @@ -23,6 +23,7 @@ import static org.apache.accumulo.test.functional.ReadWriteIT.m; import static org.apache.accumulo.test.functional.ReadWriteIT.t; import static org.apache.accumulo.test.functional.ReadWriteIT.verify; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayOutputStream; @@ -101,13 +102,25 @@ public void sunnyLG() throws Exception { try (AccumuloClient accumuloClient = Accumulo.newClient().from(getClientProps()).build()) { final String tableName = getUniqueNames(1)[0]; accumuloClient.tableOperations().create(tableName); - Map> groups = new TreeMap<>(); - groups.put("g1", Collections.singleton(t("colf"))); - accumuloClient.tableOperations().setLocalityGroups(tableName, groups); + createAndSetLocalityGroups(accumuloClient, tableName); + verifyLocalityGroupSet(accumuloClient, tableName); verifyLocalityGroupsInRFile(accumuloClient, tableName); } } + public static void createAndSetLocalityGroups(AccumuloClient client, String tableName) + throws Exception { + Map> groups = new TreeMap<>(); + groups.put("g1", Collections.singleton(t("colf"))); + client.tableOperations().setLocalityGroups(tableName, groups); + } + + public static void verifyLocalityGroupSet(AccumuloClient client, String tableName) + throws Exception { + assertEquals(Collections.singleton(t("colf")), + client.tableOperations().getLocalityGroups(tableName).get("g1")); + } + /** * Pretty much identical to sunnyLG, but verifies locality groups are created when configured in * NewTableConfiguration prior to table creation. From 4eb99ebd482139c834dbad28948a1842ab88b7d5 Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Fri, 18 Apr 2025 14:42:38 -0400 Subject: [PATCH 02/10] Changes: - Updated tests based on recent changes in main to `offline` and `getDiskUsage` - Address review comments - Trivial misc cleanup --- .../test/ComprehensiveTableOperationsIT.java | 117 ++++++++---------- 1 file changed, 51 insertions(+), 66 deletions(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java index cab2b6a8beb..e7e24ada0d7 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java @@ -28,13 +28,14 @@ import java.lang.reflect.Method; import java.time.Duration; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeSet; import java.util.UUID; @@ -49,9 +50,11 @@ import org.apache.accumulo.core.client.IteratorSetting; import org.apache.accumulo.core.client.admin.TableOperations; import org.apache.accumulo.core.client.admin.TabletAvailability; +import org.apache.accumulo.core.client.admin.TabletMergeability; import org.apache.accumulo.core.client.admin.TimeType; import org.apache.accumulo.core.client.summary.SummarizerConfiguration; import org.apache.accumulo.core.clientImpl.ClientContext; +import org.apache.accumulo.core.clientImpl.TabletMergeabilityUtil; import org.apache.accumulo.core.conf.Property; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Mutation; @@ -182,6 +185,23 @@ public void test_list_tableIdMap() throws Exception { expected.add(userTable); assertEquals(expected, ops.list()); assertEquals(expected, ops.tableIdMap().keySet()); + for (Map.Entry entry : ops.tableIdMap().entrySet()) { + var tableName = entry.getKey(); + var tableId = TableId.of(entry.getValue()); + if (tableName.equals(AccumuloTable.ROOT.tableName())) { + assertEquals(AccumuloTable.ROOT.tableId(), tableId); + } else if (tableName.equals(AccumuloTable.METADATA.tableName())) { + assertEquals(AccumuloTable.METADATA.tableId(), tableId); + } else if (tableName.equals(AccumuloTable.FATE.tableName())) { + assertEquals(AccumuloTable.FATE.tableId(), tableId); + } else if (tableName.equals(AccumuloTable.SCAN_REF.tableName())) { + assertEquals(AccumuloTable.SCAN_REF.tableId(), tableId); + } else if (tableName.equals(userTable)) { + assertFalse(AccumuloTable.allTableIds().contains(tableId)); + } else { + throw new IllegalStateException("Unrecognized table: " + tableName); + } + } } @Test @@ -233,59 +253,43 @@ public void test_exportTable_importTable() throws Exception { // not offline, can't export assertThrows(IllegalStateException.class, () -> ops.exportTable(sysTable.tableName(), exportDir.toString())); - - switch (sysTable) { - case ROOT: - case METADATA: - // can't offline, so will never be able to export - assertThrows(AccumuloException.class, () -> ops.offline(sysTable.tableName(), true)); - assertThrows(AccumuloException.class, - () -> ops.importTable(sysTable.tableName(), exportUserDir.toString())); - break; - case FATE: - case SCAN_REF: - ops.offline(sysTable.tableName(), true); - try { - assertThrows(AccumuloException.class, - () -> ops.exportTable(sysTable.tableName(), exportDir.toString())); - assertThrows(AccumuloException.class, - () -> ops.importTable(sysTable.tableName(), exportUserDir.toString())); - } finally { - ops.online(sysTable.tableName(), true); - } - break; - default: - throw new IllegalStateException("Unrecognized table: " + sysTable); - } + // can't offline, so will never be able to export + assertThrows(AccumuloException.class, () -> ops.offline(sysTable.tableName(), true)); + assertThrows(AccumuloException.class, + () -> ops.importTable(sysTable.tableName(), exportUserDir.toString())); } } @Test public void test_addSplits_putSplits_listSplits_splitRangeByTablets() throws Exception { - // note that addSplits and putSplits are implemented the same, just take different args. No - // need to test both - - // addSplits, listSplits tested elsewhere for METADATA, ROOT, and user tables, but testing here - // as well since this setup is needed to test for splitRangeByTablets anyway, which is untested - // elsewhere + // addSplits,listSplits,putSplits tested elsewhere for METADATA, ROOT, and user tables, but + // testing here as well since this setup is needed to test for splitRangeByTablets anyway, + // which is untested elsewhere userTable = getUniqueNames(1)[0]; ops.create(userTable); // system and user tables - var allTables = new ArrayList<>(ops.list()); + var allTables = ops.list(); - for (int i = 0; i < allTables.size(); i++) { - SortedSet splits = new TreeSet<>(); - splits.add(new Text(i + "")); - String table = allTables.get(i); + for (String table : allTables) { + SortedSet splits1 = new TreeSet<>(); + splits1.add(new Text("split1")); + SortedSet splits2 = new TreeSet<>(); + splits2.add(new Text("split2")); + SortedMap splits2Map = + TabletMergeabilityUtil.userDefaultSplits(splits2); if (table.equals(AccumuloTable.ROOT.tableName())) { // cannot add splits to ROOT - assertThrows(AccumuloException.class, () -> ops.addSplits(table, splits)); + assertThrows(AccumuloException.class, () -> ops.addSplits(table, splits1)); + assertThrows(AccumuloException.class, () -> ops.putSplits(table, splits2Map)); assertEquals(0, ops.listSplits(table).size()); } else { - ops.addSplits(table, splits); - assertTrue(ops.listSplits(table).containsAll(splits)); + ops.addSplits(table, splits1); + ops.putSplits(table, splits2Map); + var listSplits = ops.listSplits(table); + assertTrue(listSplits.containsAll(splits1)); + assertTrue(listSplits.containsAll(splits2)); } assertEquals(ops.splitRangeByTablets(table, new Range(), 99).size(), @@ -526,8 +530,7 @@ public void test_rename() throws Exception { for (int i = 0; i < sysTables.length; i++) { var sysTable = sysTables[i]; var tableName = tableNames[i]; - assertThrows(AccumuloException.class, - () -> client.tableOperations().rename(sysTable.tableName(), tableName)); + assertThrows(AccumuloException.class, () -> ops.rename(sysTable.tableName(), tableName)); } } @@ -635,26 +638,10 @@ public void test_offline_online_isOnline() throws Exception { assertDoesNotThrow(() -> Class.forName(ComprehensiveBaseIT.class.getName())); // offline,online,isOnline not tested for system tables. Test basic functionality here for (var sysTable : AccumuloTable.values()) { - switch (sysTable) { - case ROOT: - case METADATA: - assertTrue(client.tableOperations().isOnline(sysTable.tableName())); - assertThrows(AccumuloException.class, - () -> client.tableOperations().offline(sysTable.tableName(), true)); - assertTrue(client.tableOperations().isOnline(sysTable.tableName())); - client.tableOperations().online(sysTable.tableName(), true); - break; - case SCAN_REF: - case FATE: - assertTrue(client.tableOperations().isOnline(sysTable.tableName())); - client.tableOperations().offline(sysTable.tableName(), true); - assertFalse(client.tableOperations().isOnline(sysTable.tableName())); - client.tableOperations().online(sysTable.tableName(), true); - assertTrue(client.tableOperations().isOnline(sysTable.tableName())); - break; - default: - throw new IllegalStateException("Unrecognized table: " + sysTable); - } + assertTrue(ops.isOnline(sysTable.tableName())); + assertThrows(AccumuloException.class, () -> ops.offline(sysTable.tableName(), true)); + assertTrue(ops.isOnline(sysTable.tableName())); + ops.online(sysTable.tableName(), true); } } @@ -665,7 +652,7 @@ public void test_clearLocatorCache() throws Exception { var clientContext = (ClientContext) client; userTable = getUniqueNames(1)[0]; - client.tableOperations().create(userTable); + ops.create(userTable); ReadWriteIT.ingest(clientContext, 5, 5, 5, 0, userTable); assertTrue(clientContext.getTabletLocationCache(TableId.of(ops.tableIdMap().get(userTable))) .getTabletHostingRequestCount() > 0); @@ -753,9 +740,7 @@ public void test_getDiskUsage() throws Exception { assertEquals(1, diskUsageList.size()); var diskUsage = diskUsageList.get(0); log.info("table : {}, disk usage : {}", sysTable.tableName(), diskUsage.getUsage()); - if (!sysTable.equals(AccumuloTable.ROOT)) { - assertTrue(diskUsage.getUsage() > 0); - } + assertTrue(diskUsage.getUsage() > 0); } } @@ -855,7 +840,7 @@ private Text createFateTableRow(String table) throws Exception { // start a very slow compaction to create a FATE op that will linger in the FATE table until // cancelled - client.tableOperations().compact(table, null, null, true, false); + ops.compact(table, null, null, true, false); Set rowsSeenAfterNewOp = new HashSet<>(); try (var scanner = client.createScanner(AccumuloTable.FATE.tableName())) { From 41599c1656252e602738c46f243885cf58fe1b3f Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Fri, 18 Apr 2025 16:46:25 -0400 Subject: [PATCH 03/10] address review --- .../test/ComprehensiveTableOperationsIT.java | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java index e7e24ada0d7..5dc86cbd91d 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java @@ -137,9 +137,10 @@ public void beforeEach() { public void afterEach() throws Exception { // ensure none of the FATE or SCAN_REF data we created persists between tests. Also ensure the // user table does not persist between tests - if (userTable != null && ops.exists(userTable)) { + if (userTable != null) { cleanupFateTable(); ops.delete(userTable); + userTable = null; } cleanupScanRefTable(); client.close(); @@ -147,21 +148,14 @@ public void afterEach() throws Exception { @Test public void testAllTested() { - var allTableOps = Arrays.stream(TableOperations.class.getDeclaredMethods()).map(Method::getName) - .collect(Collectors.toSet()); + var allTableOps = + Arrays.stream(TableOperations.class.getDeclaredMethods()).map(Method::getName); var testMethodNames = Arrays.stream(ComprehensiveTableOperationsIT.class.getDeclaredMethods()) .map(Method::getName).collect(Collectors.toSet()); - var allTableOpsIter = allTableOps.iterator(); - while (allTableOpsIter.hasNext()) { - var tableOp = allTableOpsIter.next(); - for (var testMethodName : testMethodNames) { - if (testMethodName.contains(tableOp)) { - allTableOpsIter.remove(); - break; - } - } - } - assertTrue(allTableOps.isEmpty(), "The table operations " + allTableOps + " are untested"); + var untestedOps = + allTableOps.filter(op -> testMethodNames.stream().noneMatch(test -> test.contains(op))) + .collect(Collectors.toSet()); + assertTrue(untestedOps.isEmpty(), "The table operations " + untestedOps + " are untested"); } @Test @@ -219,7 +213,7 @@ public void test_exists() throws Exception { } @Test - public void test_create() throws Exception { + public void test_create() { // Creating user tables is thoroughly tested. Make sure we can't create any of the already // existing system tables, though. for (var systemTable : AccumuloTable.values()) { @@ -504,7 +498,7 @@ public void test_cancelCompaction() throws Exception { } @Test - public void test_delete() throws Exception { + public void test_delete() { // delete for user tables is tested in TableOperationsIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(TableOperationsIT.class.getName())); // delete not tested for system tables. Test basic functionality here @@ -514,13 +508,13 @@ public void test_delete() throws Exception { } @Test - public void test_clone() throws Exception { + public void test_clone() { // cloning user and system tables is tested in CloneTestIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(CloneTestIT.class.getName())); } @Test - public void test_rename() throws Exception { + public void test_rename() { // rename for user tables is tested in RenameIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(RenameIT.class.getName())); // rename not tested for system tables. Test basic functionality here @@ -919,7 +913,7 @@ private boolean propFound(String tableName, String key, String val) throws Excep return propFound; } - private Set getStoredTabFiles(AccumuloTable sysTable) throws Exception { + private Set getStoredTabFiles(AccumuloTable sysTable) { var clientContext = (ClientContext) client; Set storedTabFiles = new HashSet<>(); try (TabletsMetadata tabletsMetadata = From c88263153459d77dad6ce76bb3c7ac4449bdbde1 Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Fri, 25 Apr 2025 11:53:32 -0400 Subject: [PATCH 04/10] Address review: - Compare sets of files instead of number of files in flush - Extra check to test_setProperty_modifyProperties_removeProperty_getProperties_getTableProperties_getConfiguration --- .../test/ComprehensiveTableOperationsIT.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java index b3cb3cbe9a1..f2e01171118 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java @@ -523,25 +523,26 @@ public void test_flush() throws Exception { createScanRefTableRow(); for (var sysTable : Set.of(SystemTables.FATE, SystemTables.SCAN_REF)) { - int numFilesBeforeFlush = 0; + Set filesBeforeFlush = new HashSet<>(); try (TabletsMetadata tabletsMetadata = getCluster().getServerContext().getAmple() .readTablets().forTable(sysTable.tableId()).build()) { for (var tm : tabletsMetadata) { - numFilesBeforeFlush += tm.getFiles().size(); + filesBeforeFlush.addAll(tm.getFiles()); } } + ops.flush(sysTable.tableName(), null, null, true); - // Wait until we see the new file - final int finalNumFilesBeforeFlush = numFilesBeforeFlush; + + // Wait until the set of files changes Wait.waitFor(() -> { + Set filesAfterFlush = new HashSet<>(); try (TabletsMetadata tabletsMetadata = getCluster().getServerContext().getAmple() .readTablets().forTable(sysTable.tableId()).build()) { - int numFilesAfterFlush = 0; for (var tm : tabletsMetadata) { - numFilesAfterFlush += tm.getFiles().size(); + filesAfterFlush.addAll(tm.getFiles()); } - return numFilesAfterFlush > finalNumFilesBeforeFlush; + return !filesAfterFlush.equals(filesBeforeFlush); } }); } @@ -561,19 +562,29 @@ public void test_flush() throws Exception { String propKey = Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "prop"; String propVal = "val"; String newPropVal = "newval"; + // getProperties, getTableProperties, and getConfiguration + assertFalse(propFound(tableName, propKey, propVal)); + assertNull(ops.getTableProperties(tableName).get(propKey)); + assertNull(ops.getConfiguration(tableName).get(propKey)); + ops.setProperty(tableName, propKey, propVal); + // getProperties, getTableProperties, and getConfiguration assertTrue(propFound(tableName, propKey, propVal)); assertEquals(propVal, ops.getTableProperties(tableName).get(propKey)); assertEquals(propVal, ops.getConfiguration(tableName).get(propKey)); + // modifyProperties ops.modifyProperties(tableName, properties -> properties.put(propKey, newPropVal)); + // getProperties, getTableProperties, and getConfiguration assertTrue(propFound(tableName, propKey, newPropVal)); assertEquals(newPropVal, ops.getTableProperties(tableName).get(propKey)); assertEquals(newPropVal, ops.getConfiguration(tableName).get(propKey)); + // removeProperty ops.removeProperty(tableName, propKey); + // getProperties, getTableProperties, and getConfiguration assertFalse(propFound(tableName, propKey, newPropVal)); assertNull(ops.getTableProperties(tableName).get(propKey)); From 0badef9640592beb0171b41a421382142934f149 Mon Sep 17 00:00:00 2001 From: Dom Garguilo Date: Mon, 28 Apr 2025 16:19:05 -0400 Subject: [PATCH 05/10] Making use of new helper methods in SystemTables --- .../test/ComprehensiveTableOperationsIT.java | 121 ++++++++---------- 1 file changed, 55 insertions(+), 66 deletions(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java index f2e01171118..4bc2b1b8ca0 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java @@ -173,8 +173,7 @@ public void test_list_tableIdMap() throws Exception { // and user tables are returned userTable = getUniqueNames(1)[0]; ops.create(userTable); - var expected = Arrays.stream(SystemTables.values()).map(SystemTables::tableName) - .collect(Collectors.toSet()); + var expected = new HashSet<>(SystemTables.tableNames()); expected.add(userTable); assertEquals(expected, ops.list()); assertEquals(expected, ops.tableIdMap().keySet()); @@ -203,8 +202,7 @@ public void test_exists() throws Exception { // and user tables exist userTable = getUniqueNames(1)[0]; ops.create(userTable); - var expected = Arrays.stream(SystemTables.values()).map(SystemTables::tableName) - .collect(Collectors.toSet()); + var expected = new HashSet<>(SystemTables.tableNames()); expected.add(userTable); for (String table : expected) { assertTrue(ops.exists(table)); @@ -215,8 +213,8 @@ public void test_exists() throws Exception { public void test_create() { // Creating user tables is thoroughly tested. Make sure we can't create any of the already // existing system tables, though. - for (var systemTable : SystemTables.values()) { - assertThrows(AccumuloException.class, () -> ops.create(systemTable.tableName())); + for (var systemTable : SystemTables.tableNames()) { + assertThrows(AccumuloException.class, () -> ops.create(systemTable)); } } @@ -237,19 +235,17 @@ public void test_exportTable_importTable() throws Exception { fs.deleteOnExit(exportUserDir); ops.exportTable(userTable, exportUserDir.toString()); - var sysTables = SystemTables.values(); - for (int i = 0; i < sysTables.length; i++) { - var sysTable = sysTables[i]; - Path exportDir = new Path(baseDir, "export" + i); + for (var sysTableName : SystemTables.tableNames()) { + Path exportDir = new Path(baseDir, "export_" + sysTableName); fs.deleteOnExit(exportDir); // not offline, can't export assertThrows(IllegalStateException.class, - () -> ops.exportTable(sysTable.tableName(), exportDir.toString())); + () -> ops.exportTable(sysTableName, exportDir.toString())); // can't offline, so will never be able to export - assertThrows(AccumuloException.class, () -> ops.offline(sysTable.tableName(), true)); + assertThrows(AccumuloException.class, () -> ops.offline(sysTableName, true)); assertThrows(AccumuloException.class, - () -> ops.importTable(sysTable.tableName(), exportUserDir.toString())); + () -> ops.importTable(sysTableName, exportUserDir.toString())); } } @@ -337,9 +333,9 @@ public void test_getMaxRow_deleteRows() throws Exception { // deleteRows for user tables is tested in DeleteRowsIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(DeleteRowsIT.class.getName())); // deleteRows not tested for system tables. Test basic functionality here - for (var sysTable : SystemTables.values()) { + for (var sysTable : SystemTables.tableNames()) { // should not be able to delete rows of any system table - assertThrows(AccumuloException.class, () -> ops.deleteRows(sysTable.tableName(), null, null)); + assertThrows(AccumuloException.class, () -> ops.deleteRows(sysTable, null, null)); } } @@ -449,15 +445,15 @@ public void test_cancelCompaction() throws Exception { createFateTableRow(userTable); createScanRefTableRow(); - for (var sysTable : SystemTables.values()) { + for (var sysTable : SystemTables.tableNames()) { try { var zrw = getCluster().getServerContext().getZooSession().asReaderWriter(); - attachSlowMajcIterator(sysTable.tableName()); + attachSlowMajcIterator(sysTable); var metaFatesBeforeCompact = new HashSet<>(zrw.getChildren(Constants.ZFATE)); log.info("Compacting " + sysTable); - ops.compact(sysTable.tableName(), null, null, true, false); + ops.compact(sysTable, null, null, true, false); log.info("Initiated compaction for " + sysTable); // Wait for the compaction to be started @@ -467,15 +463,12 @@ public void test_cancelCompaction() throws Exception { }); log.info("Cancelling compaction " + sysTable); - ops.cancelCompaction(sysTable.tableName()); + ops.cancelCompaction(sysTable); // We can be sure that the compaction has been cancelled once we see no FATE operations - Wait.waitFor(() -> { - Set metaFatesAfterCancelCompact = new HashSet<>(zrw.getChildren(Constants.ZFATE)); - return metaFatesAfterCancelCompact.isEmpty(); - }); + Wait.waitFor(() -> zrw.getChildren(Constants.ZFATE).isEmpty()); } finally { - removeSlowMajcIterator(sysTable.tableName()); + removeSlowMajcIterator(sysTable); } } } @@ -485,8 +478,8 @@ public void test_delete() { // delete for user tables is tested in TableOperationsIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(TableOperationsIT.class.getName())); // delete not tested for system tables. Test basic functionality here - for (var sysTable : SystemTables.values()) { - assertThrows(AccumuloException.class, () -> ops.delete(sysTable.tableName())); + for (var sysTable : SystemTables.tableNames()) { + assertThrows(AccumuloException.class, () -> ops.delete(sysTable)); } } @@ -501,13 +494,10 @@ public void test_rename() { // rename for user tables is tested in RenameIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(RenameIT.class.getName())); // rename not tested for system tables. Test basic functionality here - var sysTables = SystemTables.values(); - var tableNames = getUniqueNames(sysTables.length); - for (int i = 0; i < sysTables.length; i++) { - var sysTable = sysTables[i]; - var tableName = tableNames[i]; - assertThrows(AccumuloException.class, () -> ops.rename(sysTable.tableName(), tableName)); + for (var sysTable : SystemTables.tableNames()) { + var e = assertThrows(AccumuloException.class, () -> ops.rename(sysTable, "newTableName")); + assertEquals("Table must not be in the 'accumulo' namespace", e.getMessage()); } } @@ -599,9 +589,9 @@ public void test_setLocalityGroups_getLocalityGroups() throws Exception { assertDoesNotThrow(() -> Class.forName(LocalityGroupIT.class.getName())); // setLocalityGroups, getLocalityGroups for system tables not tested for. Test basic // functionality here - for (var sysTable : SystemTables.values()) { - LocalityGroupIT.createAndSetLocalityGroups(client, sysTable.tableName()); - LocalityGroupIT.verifyLocalityGroupSet(client, sysTable.tableName()); + for (var sysTable : SystemTables.tableNames()) { + LocalityGroupIT.createAndSetLocalityGroups(client, sysTable); + LocalityGroupIT.verifyLocalityGroupSet(client, sysTable); } } @@ -615,8 +605,8 @@ public void test_importDirectory() throws Exception { BulkNewIT.writeData(getCluster().getFileSystem(), dir + "/f1.", getCluster().getServerContext().getConfiguration(), 0, 5, 0); - for (var sysTable : SystemTables.values()) { - assertThrows(Exception.class, () -> ops.importDirectory(dir).to(sysTable.tableName()).load()); + for (var sysTable : SystemTables.tableNames()) { + assertThrows(Exception.class, () -> ops.importDirectory(dir).to(sysTable).load()); } } @@ -625,11 +615,11 @@ public void test_offline_online_isOnline() throws Exception { // offline,online,isOnline for user tables is tested in ComprehensiveBaseIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(ComprehensiveBaseIT.class.getName())); // offline,online,isOnline not tested for system tables. Test basic functionality here - for (var sysTable : SystemTables.values()) { - assertTrue(ops.isOnline(sysTable.tableName())); - assertThrows(AccumuloException.class, () -> ops.offline(sysTable.tableName(), true)); - assertTrue(ops.isOnline(sysTable.tableName())); - ops.online(sysTable.tableName(), true); + for (var sysTable : SystemTables.tableNames()) { + assertTrue(ops.isOnline(sysTable)); + assertThrows(AccumuloException.class, () -> ops.offline(sysTable, true)); + assertTrue(ops.isOnline(sysTable)); + ops.online(sysTable, true); } } @@ -695,19 +685,19 @@ public void test_addConstraint_listConstraints_removeConstraint() throws Excepti assertDoesNotThrow(() -> Class.forName(ConstraintIT.class.getName())); // addConstraint, listConstraints, removeConstraint not tested for system tables. Test basic // functionality here - for (var sysTable : SystemTables.values()) { - var numExistingConstraints = ops.listConstraints(sysTable.tableName()).size(); + for (var sysTable : SystemTables.tableNames()) { + var numExistingConstraints = ops.listConstraints(sysTable).size(); String constraint = ComprehensiveBaseIT.TestConstraint.class.getName(); - var constraintNum = ops.addConstraint(sysTable.tableName(), constraint); + var constraintNum = ops.addConstraint(sysTable, constraint); - var listConstraints = ops.listConstraints(sysTable.tableName()); + var listConstraints = ops.listConstraints(sysTable); assertEquals(numExistingConstraints + 1, listConstraints.size()); assertEquals(constraintNum, listConstraints.get(constraint)); - ops.removeConstraint(sysTable.tableName(), constraintNum); + ops.removeConstraint(sysTable, constraintNum); - listConstraints = ops.listConstraints(sysTable.tableName()); + listConstraints = ops.listConstraints(sysTable); assertEquals(numExistingConstraints, listConstraints.size()); assertNull(listConstraints.get(constraint)); } @@ -722,12 +712,12 @@ public void test_getDiskUsage() throws Exception { ops.create(userTable); createFateTableRow(userTable); createScanRefTableRow(); - for (var sysTable : SystemTables.values()) { - ops.flush(sysTable.tableName(), null, null, true); - var diskUsageList = ops.getDiskUsage(Set.of(sysTable.tableName())); + for (var sysTable : SystemTables.tableNames()) { + ops.flush(sysTable, null, null, true); + var diskUsageList = ops.getDiskUsage(Set.of(sysTable)); assertEquals(1, diskUsageList.size()); var diskUsage = diskUsageList.get(0); - log.info("table : {}, disk usage : {}", sysTable.tableName(), diskUsage.getUsage()); + log.info("table : {}, disk usage : {}", sysTable, diskUsage.getUsage()); assertTrue(diskUsage.getUsage() > 0); } } @@ -768,15 +758,14 @@ public void test_summaries_addSummarizers_removeSummarizers_listSummarizers() th // these are all tested for user tables in SummaryIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(SummaryIT.class.getName())); // these are not tested for system tables. Test basic functionality here - for (var sysTable : SystemTables.values()) { + for (var sysTable : SystemTables.tableNames()) { SummarizerConfiguration sc = SummarizerConfiguration.builder(BasicSummarizer.class).build(); - assertThrows(AccumuloSecurityException.class, - () -> ops.summaries(sysTable.tableName()).retrieve()); - ops.addSummarizers(sysTable.tableName(), sc); - assertEquals(List.of(sc), ops.listSummarizers(sysTable.tableName())); - ops.removeSummarizers(sysTable.tableName(), sc1 -> true); - assertTrue(ops.listSummarizers(sysTable.tableName()).isEmpty()); + assertThrows(AccumuloSecurityException.class, () -> ops.summaries(sysTable).retrieve()); + ops.addSummarizers(sysTable, sc); + assertEquals(List.of(sc), ops.listSummarizers(sysTable)); + ops.removeSummarizers(sysTable, sc1 -> true); + assertTrue(ops.listSummarizers(sysTable).isEmpty()); } } @@ -788,8 +777,8 @@ public void test_getTimeType() throws Exception { ops.create(userTable); assertEquals(TimeType.MILLIS, ops.getTimeType(userTable)); - for (var sysTable : SystemTables.values()) { - assertEquals(TimeType.LOGICAL, ops.getTimeType(sysTable.tableName())); + for (var sysTable : SystemTables.tableNames()) { + assertEquals(TimeType.LOGICAL, ops.getTimeType(sysTable)); } } @@ -798,12 +787,12 @@ public void test_setTabletAvailability_getTabletInformation() throws Exception { // these are tested for user tables in TabletAvailabilityIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(TabletAvailabilityIT.class.getName())); // these are not tested for system tables. Test basic functionality here - for (var sysTable : SystemTables.values()) { + for (var sysTable : SystemTables.tableNames()) { // should not be able to unhost any system table - assertThrows(IllegalArgumentException.class, () -> ops - .setTabletAvailability(sysTable.tableName(), new Range(), TabletAvailability.UNHOSTED)); - assertTrue(ops.getTabletInformation(sysTable.tableName(), new Range()).findAny().isPresent()); - ops.getTabletInformation(sysTable.tableName(), new Range()) + assertThrows(IllegalArgumentException.class, + () -> ops.setTabletAvailability(sysTable, new Range(), TabletAvailability.UNHOSTED)); + assertTrue(ops.getTabletInformation(sysTable, new Range()).findAny().isPresent()); + ops.getTabletInformation(sysTable, new Range()) .forEach(ti -> assertEquals(TabletAvailability.HOSTED, ti.getTabletAvailability())); } } From d49df4e303e95845f70374aa53144359d35f8f98 Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Mon, 28 Apr 2025 17:05:52 -0400 Subject: [PATCH 06/10] improved test_rename --- .../test/ComprehensiveTableOperationsIT.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java index 4bc2b1b8ca0..9a023930561 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java @@ -323,9 +323,9 @@ public void test_getMaxRow_deleteRows() throws Exception { ops.create(userTable); createFateTableRow(userTable); createScanRefTableRow(); - for (var sysTable : SystemTables.values()) { + for (var sysTable : SystemTables.tableNames()) { var maxRow = - ops.getMaxRow(sysTable.tableName(), Authorizations.EMPTY, null, true, null, true); + ops.getMaxRow(sysTable, Authorizations.EMPTY, null, true, null, true); log.info("Max row of {} : {}", sysTable, maxRow); assertNotNull(maxRow); } @@ -490,14 +490,18 @@ public void test_clone() { } @Test - public void test_rename() { + public void test_rename() throws Exception { // rename for user tables is tested in RenameIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(RenameIT.class.getName())); // rename not tested for system tables. Test basic functionality here + String newTableName = "newTableName"; + userTable = getUniqueNames(1)[0]; + ops.create(userTable); for (var sysTable : SystemTables.tableNames()) { - var e = assertThrows(AccumuloException.class, () -> ops.rename(sysTable, "newTableName")); - assertEquals("Table must not be in the 'accumulo' namespace", e.getMessage()); + assertThrows(AccumuloException.class, () -> ops.rename(sysTable, newTableName)); + assertFalse(ops.exists(newTableName)); + assertThrows(AccumuloException.class, () -> ops.rename(userTable, sysTable)); } } From 53ba7f24b28120f0d060a45b3ef09971b1b6824b Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Mon, 28 Apr 2025 17:11:01 -0400 Subject: [PATCH 07/10] formatting --- .../apache/accumulo/test/ComprehensiveTableOperationsIT.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java index 9a023930561..478a23e373f 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java @@ -324,8 +324,7 @@ public void test_getMaxRow_deleteRows() throws Exception { createFateTableRow(userTable); createScanRefTableRow(); for (var sysTable : SystemTables.tableNames()) { - var maxRow = - ops.getMaxRow(sysTable, Authorizations.EMPTY, null, true, null, true); + var maxRow = ops.getMaxRow(sysTable, Authorizations.EMPTY, null, true, null, true); log.info("Max row of {} : {}", sysTable, maxRow); assertNotNull(maxRow); } From 8a3486030a01851327fbdffa309e6a57ba6899d4 Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Wed, 25 Jun 2025 12:43:55 -0400 Subject: [PATCH 08/10] minor changes: - ComprehensiveTableOperationsIT -> ComprehensiveTableOperationsIT_SimpleSuite so it's part of the new test suite - Added back method SystemTables.tableNames() which was deleted for some reason. Most likely was deleted due to no use cases, but it is a useful util and this PR was using it, so added it back. - deleted test_compact test, opened issue #5679 for it - Some test classes were renamed and were referenced here, so resolved those --- .../accumulo/core/metadata/SystemTables.java | 4 + ...hensiveTableOperationsIT_SimpleSuite.java} | 86 ++++--------------- 2 files changed, 20 insertions(+), 70 deletions(-) rename test/src/main/java/org/apache/accumulo/test/{ComprehensiveTableOperationsIT.java => ComprehensiveTableOperationsIT_SimpleSuite.java} (90%) diff --git a/core/src/main/java/org/apache/accumulo/core/metadata/SystemTables.java b/core/src/main/java/org/apache/accumulo/core/metadata/SystemTables.java index bc3796f0a25..aec1be7ea31 100644 --- a/core/src/main/java/org/apache/accumulo/core/metadata/SystemTables.java +++ b/core/src/main/java/org/apache/accumulo/core/metadata/SystemTables.java @@ -80,6 +80,10 @@ public static Set tableIds() { return ALL_IDS; } + public static Set tableNames() { + return ALL_NAMES; + } + public static boolean containsTableId(TableId tableId) { return ALL_IDS.contains(tableId); } diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java similarity index 90% rename from test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java rename to test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java index 478a23e373f..2f2c8cb514f 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java @@ -57,7 +57,6 @@ import org.apache.accumulo.core.clientImpl.TabletMergeabilityUtil; import org.apache.accumulo.core.conf.Property; import org.apache.accumulo.core.data.Key; -import org.apache.accumulo.core.data.Mutation; import org.apache.accumulo.core.data.Range; import org.apache.accumulo.core.data.TableId; import org.apache.accumulo.core.data.Value; @@ -71,16 +70,15 @@ import org.apache.accumulo.core.metadata.schema.TabletsMetadata; import org.apache.accumulo.core.security.Authorizations; import org.apache.accumulo.harness.SharedMiniClusterBase; -import org.apache.accumulo.minicluster.ServerType; import org.apache.accumulo.test.functional.BasicSummarizer; import org.apache.accumulo.test.functional.BulkNewIT; -import org.apache.accumulo.test.functional.CloneTestIT; +import org.apache.accumulo.test.functional.CloneTestIT_SimpleSuite; import org.apache.accumulo.test.functional.CompactionIT; import org.apache.accumulo.test.functional.ConstraintIT; import org.apache.accumulo.test.functional.DeleteRowsIT; import org.apache.accumulo.test.functional.LocalityGroupIT; import org.apache.accumulo.test.functional.ManagerAssignmentIT; -import org.apache.accumulo.test.functional.MergeTabletsIT; +import org.apache.accumulo.test.functional.MergeTabletsIT_SimpleSuite; import org.apache.accumulo.test.functional.ReadWriteIT; import org.apache.accumulo.test.functional.RenameIT; import org.apache.accumulo.test.functional.SlowIterator; @@ -105,8 +103,9 @@ * avoiding duplicating existing testing. This does not test for edge cases, but rather tests for * basic expected functionality of all table operations against user tables and all system tables. */ -public class ComprehensiveTableOperationsIT extends SharedMiniClusterBase { - private static final Logger log = LoggerFactory.getLogger(ComprehensiveTableOperationsIT.class); +public class ComprehensiveTableOperationsIT_SimpleSuite extends SharedMiniClusterBase { + private static final Logger log = + LoggerFactory.getLogger(ComprehensiveTableOperationsIT_SimpleSuite.class); private static final String SLOW_ITER_NAME = "CustomSlowIter"; private AccumuloClient client; private TableOperations ops; @@ -150,8 +149,9 @@ public void afterEach() throws Exception { public void testAllTested() { var allTableOps = Arrays.stream(TableOperations.class.getDeclaredMethods()).map(Method::getName); - var testMethodNames = Arrays.stream(ComprehensiveTableOperationsIT.class.getDeclaredMethods()) - .map(Method::getName).collect(Collectors.toSet()); + var testMethodNames = + Arrays.stream(ComprehensiveTableOperationsIT_SimpleSuite.class.getDeclaredMethods()) + .map(Method::getName).collect(Collectors.toSet()); var untestedOps = allTableOps.filter(op -> testMethodNames.stream().noneMatch(test -> test.contains(op))) .collect(Collectors.toSet()); @@ -342,7 +342,7 @@ public void test_getMaxRow_deleteRows() throws Exception { public void test_merge() throws Exception { // merge for user tables is tested in various ITs. One example is MergeTabletsIT. Ensure // test exists - assertDoesNotThrow(() -> Class.forName(MergeTabletsIT.class.getName())); + assertDoesNotThrow(() -> Class.forName(MergeTabletsIT_SimpleSuite.class.getName())); // merge for METADATA and ROOT system tables tested in MetaSplitIT. Ensure test exists assertDoesNotThrow(() -> Class.forName(MetaSplitIT.class.getName())); // merge for FATE and SCAN_REF tables not tested. Test basic functionality here @@ -372,61 +372,7 @@ public void test_merge() throws Exception { @Test public void test_compact() throws Exception { - // compact for user tables is tested in various ITs. One example is CompactionIT. Ensure - // test exists - assertDoesNotThrow(() -> Class.forName(CompactionIT.class.getName())); - // disable the GC to prevent automatic compactions on METADATA and ROOT tables - getCluster().getClusterControl().stopAllServers(ServerType.GARBAGE_COLLECTOR); - try { - // test basic functionality for system tables - userTable = getUniqueNames(1)[0]; - ops.create(userTable); - - // create some RFiles for the METADATA and ROOT tables by creating some data in the user - // table, flushing that table, then the METADATA table, then the ROOT table - for (int i = 0; i < 3; i++) { - try (var bw = client.createBatchWriter(userTable)) { - var mut = new Mutation("r" + i); - mut.put("cf", "cq", "v"); - bw.addMutation(mut); - } - ops.flush(userTable, null, null, true); - ops.flush(SystemTables.METADATA.tableName(), null, null, true); - ops.flush(SystemTables.ROOT.tableName(), null, null, true); - } - - for (var sysTable : List.of(SystemTables.ROOT, SystemTables.METADATA, SystemTables.SCAN_REF, - SystemTables.FATE)) { - // create some RFiles for FATE and SCAN_REF tables - if (sysTable == SystemTables.SCAN_REF) { - createScanRefTableRow(); - ops.flush(SystemTables.SCAN_REF.tableName(), null, null, true); - } else if (sysTable == SystemTables.FATE) { - createFateTableRow(userTable); - ops.flush(SystemTables.FATE.tableName(), null, null, true); - } - - Set stfsBeforeCompact = getStoredTabFiles(sysTable); - - log.info("Compacting " + sysTable); - ops.compact(sysTable.tableName(), null, null, true, true); - log.info("Finished compacting " + sysTable); - - // RFiles resulting from a compaction begin with 'A'. Wait until we see an RFile beginning - // with 'A' that was not present before the compaction. - Wait.waitFor(() -> { - var stfsAfterCompact = getStoredTabFiles(sysTable); - String regex = "^A.*\\.rf$"; - var A_stfsBeforeCompaction = stfsBeforeCompact.stream() - .filter(stf -> stf.getFileName().matches(regex)).collect(Collectors.toSet()); - var A_stfsAfterCompaction = stfsAfterCompact.stream() - .filter(stf -> stf.getFileName().matches(regex)).collect(Collectors.toSet()); - return !Sets.difference(A_stfsAfterCompaction, A_stfsBeforeCompaction).isEmpty(); - }); - } - } finally { - getCluster().getClusterControl().startAllServers(ServerType.GARBAGE_COLLECTOR); - } + // TODO } @Test @@ -485,7 +431,7 @@ public void test_delete() { @Test public void test_clone() { // cloning user and system tables is tested in CloneTestIT. Ensure test exists - assertDoesNotThrow(() -> Class.forName(CloneTestIT.class.getName())); + assertDoesNotThrow(() -> Class.forName(CloneTestIT_SimpleSuite.class.getName())); } @Test @@ -615,8 +561,8 @@ public void test_importDirectory() throws Exception { @Test public void test_offline_online_isOnline() throws Exception { - // offline,online,isOnline for user tables is tested in ComprehensiveBaseIT. Ensure test exists - assertDoesNotThrow(() -> Class.forName(ComprehensiveBaseIT.class.getName())); + // offline,online,isOnline for user tables is tested in ComprehensiveITBase. Ensure test exists + assertDoesNotThrow(() -> Class.forName(ComprehensiveITBase.class.getName())); // offline,online,isOnline not tested for system tables. Test basic functionality here for (var sysTable : SystemTables.tableNames()) { assertTrue(ops.isOnline(sysTable)); @@ -690,7 +636,7 @@ public void test_addConstraint_listConstraints_removeConstraint() throws Excepti // functionality here for (var sysTable : SystemTables.tableNames()) { var numExistingConstraints = ops.listConstraints(sysTable).size(); - String constraint = ComprehensiveBaseIT.TestConstraint.class.getName(); + String constraint = ComprehensiveITBase.TestConstraint.class.getName(); var constraintNum = ops.addConstraint(sysTable, constraint); @@ -749,8 +695,8 @@ public void test_setSamplerConfiguration_getSamplerConfiguration_clearSamplerCon // system and user tables Set allTables = ops.list(); for (var table : allTables) { - ops.setSamplerConfiguration(table, SampleIT.SC1); - assertEquals(SampleIT.SC1, ops.getSamplerConfiguration(table)); + ops.setSamplerConfiguration(table, SampleIT_SimpleSuite.SC1); + assertEquals(SampleIT_SimpleSuite.SC1, ops.getSamplerConfiguration(table)); ops.clearSamplerConfiguration(table); assertNull(ops.getSamplerConfiguration(table)); } From fd335cafe2004ea1f1e8f4c2f1222de9c8f2f5d3 Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Wed, 25 Jun 2025 12:51:04 -0400 Subject: [PATCH 09/10] added issue number in test_compact --- .../test/ComprehensiveTableOperationsIT_SimpleSuite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java index 2f2c8cb514f..c41427aa4b6 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java @@ -372,7 +372,7 @@ public void test_merge() throws Exception { @Test public void test_compact() throws Exception { - // TODO + // TODO see issue#5679 } @Test From 937e4f8c595b128e94a32ab0e2b687a0ff8cfe31 Mon Sep 17 00:00:00 2001 From: Kevin Rathbun Date: Wed, 25 Jun 2025 12:58:16 -0400 Subject: [PATCH 10/10] changed an expected exception type as changed by #5510 --- .../test/ComprehensiveTableOperationsIT_SimpleSuite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java index c41427aa4b6..4112fc0a8de 100644 --- a/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java +++ b/test/src/main/java/org/apache/accumulo/test/ComprehensiveTableOperationsIT_SimpleSuite.java @@ -738,7 +738,7 @@ public void test_setTabletAvailability_getTabletInformation() throws Exception { // these are not tested for system tables. Test basic functionality here for (var sysTable : SystemTables.tableNames()) { // should not be able to unhost any system table - assertThrows(IllegalArgumentException.class, + assertThrows(AccumuloException.class, () -> ops.setTabletAvailability(sysTable, new Range(), TabletAvailability.UNHOSTED)); assertTrue(ops.getTabletInformation(sysTable, new Range()).findAny().isPresent()); ops.getTabletInformation(sysTable, new Range())