Skip to content

Commit d37310c

Browse files
committed
HADOOP-19385. S3A: iceberg bulk delete test (Java17+)
Add Iceberg core to the hadoop-aws test classpath. Iceberg is java17+ only, so this adds * A new test source path src/test/java17 * A new profile "java-17-or-later" which includes this and declares the dependency on iceberg-core. The new test is ITestIcebergBulkDelete; it is parameterized Iceberg bulk delete enabled/disabled and s3a multipart delete enabled/disabled. There is a superclass contract test org.apache.fs.test.formats.AbstractIcebergDeleteTest To support future stores which implement bulk delete. This is currently a minimal superclass; all tests are currently in ITestIcebergBulkDelete Change-Id: Ica8682f4efdd0cb04ca7f4762b2e47d396552910
1 parent 0432761 commit d37310c

File tree

13 files changed

+610
-28
lines changed

13 files changed

+610
-28
lines changed

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/AbstractContractBulkDeleteTest.java

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import org.apache.hadoop.io.wrappedio.WrappedIO;
3737
import org.apache.hadoop.io.wrappedio.impl.DynamicWrappedIO;
3838

39+
import static org.apache.hadoop.fs.contract.ContractTestUtils.assertSuccessfulBulkDelete;
40+
import static org.apache.hadoop.fs.contract.ContractTestUtils.createListOfPaths;
3941
import static org.apache.hadoop.fs.contract.ContractTestUtils.skip;
4042
import static org.apache.hadoop.fs.contract.ContractTestUtils.touch;
4143
import static org.apache.hadoop.io.wrappedio.WrappedIO.bulkDelete_delete;
@@ -210,6 +212,20 @@ public void testDeletePathsNotExists() throws Exception {
210212
assertSuccessfulBulkDelete(bulkDelete_delete(getFileSystem(), basePath, paths));
211213
}
212214

215+
/**
216+
* Use a more complex filename.
217+
* This validates that any conversions to URI/string
218+
* when passing to an object store is correct.
219+
*/
220+
@Test
221+
public void testDeleteComplexFilename() throws Exception {
222+
Path path = new Path(basePath, "child[=comple]x");
223+
List<Path> paths = new ArrayList<>();
224+
paths.add(path);
225+
// bulk delete call doesn't verify if a path exist or not before deleting.
226+
assertSuccessfulBulkDelete(bulkDelete_delete(getFileSystem(), basePath, paths));
227+
}
228+
213229
@Test
214230
public void testDeletePathsDirectory() throws Exception {
215231
List<Path> paths = new ArrayList<>();
@@ -333,28 +349,4 @@ public void testChildPaths() throws Exception {
333349
assertSuccessfulBulkDelete(bulkDelete_delete(getFileSystem(), basePath, paths));
334350
}
335351

336-
337-
/**
338-
* Assert on returned entries after bulk delete operation.
339-
* Entries should be empty after successful delete.
340-
*/
341-
public static void assertSuccessfulBulkDelete(List<Map.Entry<Path, String>> entries) {
342-
Assertions.assertThat(entries)
343-
.describedAs("Bulk delete failed, " +
344-
"return entries should be empty after successful delete")
345-
.isEmpty();
346-
}
347-
348-
/**
349-
* Create a list of paths with the given count
350-
* under the given base path.
351-
*/
352-
private List<Path> createListOfPaths(int count, Path basePath) {
353-
List<Path> paths = new ArrayList<>();
354-
for (int i = 0; i < count; i++) {
355-
Path path = new Path(basePath, "file-" + i);
356-
paths.add(path);
357-
}
358-
return paths;
359-
}
360352
}

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/ContractTestUtils.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import java.util.HashSet;
5656
import java.util.List;
5757
import java.util.Locale;
58+
import java.util.Map;
5859
import java.util.NoSuchElementException;
5960
import java.util.Properties;
6061
import java.util.Set;
@@ -1825,6 +1826,48 @@ public static long totalReadSize(final List<FileRange> fileRanges) {
18251826
.sum();
18261827
}
18271828

1829+
/**
1830+
* Assert on returned entries after bulk delete operation.
1831+
* Entries should be empty after successful delete.
1832+
*/
1833+
public static void assertSuccessfulBulkDelete(List<Map.Entry<Path, String>> entries) {
1834+
Assertions.assertThat(entries)
1835+
.describedAs("Bulk delete failed, " +
1836+
"return entries should be empty after successful delete")
1837+
.isEmpty();
1838+
}
1839+
1840+
/**
1841+
* Get a file status value or, if the path doesn't exist, return null.
1842+
* @param fs filesystem
1843+
* @param path path
1844+
* @return status or null
1845+
* @throws IOException Any IO Failure other than file not found.
1846+
*/
1847+
public static final FileStatus getFileStatusOrNull(
1848+
final FileSystem fs,
1849+
final Path path)
1850+
throws IOException {
1851+
try {
1852+
return fs.getFileStatus(path);
1853+
} catch (FileNotFoundException e) {
1854+
return null;
1855+
}
1856+
}
1857+
1858+
/**
1859+
* Create a list of paths with the given count
1860+
* under the given base path.
1861+
*/
1862+
public static List<Path> createListOfPaths(int count, Path basePath) {
1863+
List<Path> paths = new ArrayList<>();
1864+
for (int i = 0; i < count; i++) {
1865+
Path path = new Path(basePath, "file-" + i);
1866+
paths.add(path);
1867+
}
1868+
return paths;
1869+
}
1870+
18281871
/**
18291872
* Results of recursive directory creation/scan operations.
18301873
*/

hadoop-project/pom.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,17 @@
787787
<version>${hadoop.version}</version>
788788
<type>test-jar</type>
789789
</dependency>
790-
790+
<dependency>
791+
<groupId>org.apache.hadoop</groupId>
792+
<artifactId>hadoop-format-testing</artifactId>
793+
<version>${hadoop.version}</version>
794+
</dependency>
795+
<dependency>
796+
<groupId>org.apache.hadoop</groupId>
797+
<artifactId>hadoop-format-testing</artifactId>
798+
<version>${hadoop.version}</version>
799+
<type>test-jar</type>
800+
</dependency>
791801
<dependency>
792802
<groupId>com.google.guava</groupId>
793803
<artifactId>guava</artifactId>

hadoop-tools/hadoop-aws/pom.xml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
<job.id>00</job.id>
5757
<!-- are root tests enabled. Set to false when running parallel jobs on same bucket -->
5858
<root.tests.enabled>unset</root.tests.enabled>
59+
60+
<!-- iceberg is java 17+ -->
61+
<!-- This requires the changes of the matching PR -->
62+
<iceberg.version>1.8.0-SNAPSHOT</iceberg.version>
5963
</properties>
6064

6165
<profiles>
@@ -312,6 +316,69 @@
312316
</properties>
313317
</profile>
314318

319+
<!-- Adds a *test only* java 17 build profile-->
320+
<profile>
321+
<id>java-17-or-later</id>
322+
<activation>
323+
<jdk>[17,)</jdk>
324+
</activation>
325+
<build>
326+
<plugins>
327+
<plugin>
328+
<groupId>org.codehaus.mojo</groupId>
329+
<artifactId>build-helper-maven-plugin</artifactId>
330+
<executions>
331+
<execution>
332+
<id>add-java17-test-source</id>
333+
<phase>generate-test-sources</phase>
334+
<goals>
335+
<goal>add-test-source</goal>
336+
</goals>
337+
<configuration>
338+
<sources>
339+
<source>${basedir}/src/test/java17</source>
340+
</sources>
341+
</configuration>
342+
</execution>
343+
</executions>
344+
</plugin>
345+
</plugins>
346+
</build>
347+
<dependencies>
348+
349+
<!-- Apache Iceberg, used for testing/regression testing BulkDelete -->
350+
<!-- iceberg is java 17+ and so can only be referenced in java 17+ test source trees -->
351+
<dependency>
352+
<groupId>org.apache.iceberg</groupId>
353+
<artifactId>iceberg-core</artifactId>
354+
<version>${iceberg.version}</version>
355+
<scope>test</scope>
356+
<exclusions>
357+
<exclusion>
358+
<groupId>org.apache.httpcomponents.core5</groupId>
359+
<artifactId>*</artifactId>
360+
</exclusion>
361+
<exclusion>
362+
<groupId>org.apache.httpcomponents.client5</groupId>
363+
<artifactId>*</artifactId>
364+
</exclusion>
365+
<exclusion>
366+
<groupId>com.fasterxml.jackson.core</groupId>
367+
<artifactId>*</artifactId>
368+
</exclusion>
369+
<exclusion>
370+
<groupId>io.airlift</groupId>
371+
<artifactId>aircompressor</artifactId>
372+
</exclusion>
373+
<exclusion>
374+
<groupId>org.checkerframework</groupId>
375+
<artifactId>checker-qual</artifactId>
376+
</exclusion>
377+
</exclusions>
378+
</dependency>
379+
</dependencies>
380+
</profile>
381+
315382
</profiles>
316383

317384
<build>

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/Constants.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,13 @@ private Constants() {
15211521
*/
15221522
public static final String FS_S3A_PERFORMANCE_FLAGS =
15231523
"fs.s3a.performance.flags";
1524+
1525+
/**
1526+
* All performance flags in the enumeration.
1527+
*/
1528+
public static final String PERFORMANCE_FLAGS =
1529+
"create, delete, mkdir, open";
1530+
15241531
/**
15251532
* Prefix for adding a header to the object when created.
15261533
* The actual value must have a "." suffix and then the actual header.

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/impl/BulkDeleteOperation.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.util.List;
2424
import java.util.Map;
2525

26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
2628
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
2729

2830
import org.apache.hadoop.fs.BulkDelete;
@@ -42,6 +44,9 @@
4244
*/
4345
public class BulkDeleteOperation extends AbstractStoreOperation implements BulkDelete {
4446

47+
private static final Logger LOG = LoggerFactory.getLogger(
48+
BulkDeleteOperation.class);
49+
4550
private final BulkDeleteOperationCallbacks callbacks;
4651

4752
private final Path basePath;
@@ -78,14 +83,18 @@ public Path basePath() {
7883
public List<Map.Entry<Path, String>> bulkDelete(final Collection<Path> paths)
7984
throws IOException, IllegalArgumentException {
8085
requireNonNull(paths);
81-
checkArgument(paths.size() <= pageSize,
82-
"Number of paths (%d) is larger than the page size (%d)", paths.size(), pageSize);
86+
final int size = paths.size();
87+
LOG.debug("bulkDelete() of {} paths with pagesize {}",
88+
size, pageSize);
89+
checkArgument(size <= pageSize,
90+
"Number of paths (%d) is larger than the page size (%d)", size, pageSize);
8391
final StoreContext context = getStoreContext();
8492
final List<ObjectIdentifier> objects = paths.stream().map(p -> {
8593
checkArgument(p.isAbsolute(), "Path %s is not absolute", p);
8694
checkArgument(validatePathIsUnderParent(p, basePath),
8795
"Path %s is not under the base path %s", p, basePath);
8896
final String k = context.pathToKey(p);
97+
LOG.debug("path \"{}\" mapped to \"{}\"", p, k);
8998
return ObjectIdentifier.builder().key(k).build();
9099
}).collect(toList());
91100

hadoop-tools/hadoop-aws/src/site/markdown/tools/hadoop-aws/testing.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,17 @@ mvn verify -Dparallel-tests -Dprefetch -DtestsThreadCount=8
350350
mvn verify -Dparallel-tests -Dprefetch -Dscale -DtestsThreadCount=8
351351
```
352352

353+
## <a name="java17"></a> Java 17 Tests
354+
355+
This module includes a test source tree which compiles and runs on
356+
Java 17+ _only_. This is to allow external libraries to be used
357+
in testing -libraries which have been built on Java 17 and cannot
358+
be loaded on older versions.
359+
360+
* This source tree is `src/test/java17`.
361+
* It may depend upon any library is built on Java 17 or later.
362+
* It is for testing only.
363+
353364
## <a name="scale"></a> Scale Tests
354365

355366
There are a set of tests designed to measure the scalability and performance

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/contract/s3a/ITestS3AContractBulkDelete.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.apache.hadoop.fs.statistics.MeanStatistic;
4242

4343
import static java.util.stream.Collectors.toList;
44+
import static org.apache.hadoop.fs.contract.ContractTestUtils.assertSuccessfulBulkDelete;
4445
import static org.apache.hadoop.fs.contract.ContractTestUtils.skip;
4546
import static org.apache.hadoop.fs.contract.ContractTestUtils.touch;
4647
import static org.apache.hadoop.fs.s3a.S3ATestUtils.*;

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/auth/ITestAssumeRole.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
import org.apache.hadoop.fs.s3a.statistics.CommitterStatistics;
6363
import org.apache.hadoop.io.wrappedio.WrappedIO;
6464

65-
import static org.apache.hadoop.fs.contract.AbstractContractBulkDeleteTest.assertSuccessfulBulkDelete;
65+
import static org.apache.hadoop.fs.contract.ContractTestUtils.assertSuccessfulBulkDelete;
6666
import static org.apache.hadoop.fs.contract.ContractTestUtils.skip;
6767
import static org.apache.hadoop.fs.contract.ContractTestUtils.touch;
6868
import static org.apache.hadoop.fs.s3a.Constants.*;

0 commit comments

Comments
 (0)