rangareddy commented on code in PR #19470:
URL: https://github.com/apache/hudi/pull/19470#discussion_r3704438904


##########
hudi-hadoop-common/src/test/java/org/apache/hudi/hadoop/fs/TestHadoopFSUtils.java:
##########
@@ -22,22 +22,80 @@
 import org.apache.hudi.storage.StoragePath;
 import org.apache.hudi.storage.StoragePathInfo;
 
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataInputStream;
 import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.FilterFileSystem;
 import org.apache.hadoop.fs.Path;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.ValueSource;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
 import static 
org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToHadoopFileStatus;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToHadoopPath;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToStoragePath;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToStoragePathInfo;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 /**
  * Tests {@link HadoopFSUtils}
  */
 public class TestHadoopFSUtils {
+  /**
+   * HUDI-4602: {@link FileSystem#getScheme()} is optional in Hadoop -- the 
base implementation throws
+   * {@link UnsupportedOperationException} -- and proxy implementations such 
as Presto's
+   * {@code PrestoS3FileSystem} do not override it. Opening a log file went 
straight through
+   * {@code isGCSFileSystem}, so a MOR {@code _rt} query on Presto failed with
+   * "Not implemented by the PrestoS3FileSystem FileSystem implementation" 
rather than reading anything.
+   *
+   * <p>{@link FilterFileSystem} has the same shape: it leaves {@code 
getScheme()} to the throwing base
+   * implementation while overriding {@code getUri()}.
+   */
+  @Test
+  public void testGetFSDataInputStreamWhenGetSchemeIsUnimplemented(@TempDir 
File tempDir) throws IOException {
+    File file = new File(tempDir, "log.file");
+    byte[] contents = new byte[] {1, 2, 3, 4};
+    Files.write(file.toPath(), contents);
+    // newInstanceLocal rather than getLocal, so closing this does not evict a 
cached FileSystem that
+    // other tests in the same JVM share.
+    try (FileSystem fs = new FilterFileSystem(FileSystem.newInstanceLocal(new 
Configuration()))) {

Review Comment:
   Extracted, with the premise assertion inside it so it cannot drift between 
call sites:
   
   ```java
   /** A FileSystem with the reported shape: {@code getUri()} works, {@code 
getScheme()} throws. */
   private static FileSystem newFsWithoutGetScheme(FileSystem delegate) {
     FileSystem fs = new FilterFileSystem(delegate);
     // The premise of every assertion below: this is the call the read path 
used to make unguarded.
     assertThrows(UnsupportedOperationException.class, fs::getScheme);
     return fs;
   }
   ```
   
   There is a second fixture alongside it, `NoSchemeFileSystem`, for the cases 
that need a chosen URI (`gs://`, `ofs://`, scheme-less) rather than the 
delegate's.
   



##########
hudi-hadoop-common/src/test/java/org/apache/hudi/hadoop/fs/TestHadoopFSUtils.java:
##########
@@ -22,22 +22,80 @@
 import org.apache.hudi.storage.StoragePath;
 import org.apache.hudi.storage.StoragePathInfo;
 
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataInputStream;
 import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.FilterFileSystem;
 import org.apache.hadoop.fs.Path;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.ValueSource;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
 import static 
org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToHadoopFileStatus;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToHadoopPath;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToStoragePath;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToStoragePathInfo;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 /**
  * Tests {@link HadoopFSUtils}
  */
 public class TestHadoopFSUtils {
+  /**
+   * HUDI-4602: {@link FileSystem#getScheme()} is optional in Hadoop -- the 
base implementation throws
+   * {@link UnsupportedOperationException} -- and proxy implementations such 
as Presto's
+   * {@code PrestoS3FileSystem} do not override it. Opening a log file went 
straight through
+   * {@code isGCSFileSystem}, so a MOR {@code _rt} query on Presto failed with
+   * "Not implemented by the PrestoS3FileSystem FileSystem implementation" 
rather than reading anything.
+   *
+   * <p>{@link FilterFileSystem} has the same shape: it leaves {@code 
getScheme()} to the throwing base
+   * implementation while overriding {@code getUri()}.
+   */
+  @Test
+  public void testGetFSDataInputStreamWhenGetSchemeIsUnimplemented(@TempDir 
File tempDir) throws IOException {
+    File file = new File(tempDir, "log.file");
+    byte[] contents = new byte[] {1, 2, 3, 4};
+    Files.write(file.toPath(), contents);
+    // newInstanceLocal rather than getLocal, so closing this does not evict a 
cached FileSystem that
+    // other tests in the same JVM share.
+    try (FileSystem fs = new FilterFileSystem(FileSystem.newInstanceLocal(new 
Configuration()))) {
+      // The premise: this is the call the read path used to make unguarded.
+      assertThrows(UnsupportedOperationException.class, fs::getScheme);
+
+      try (FSDataInputStream stream =
+               HadoopFSUtils.getFSDataInputStream(fs, new 
StoragePath(file.toURI()), 1024, true)) {
+        byte[] read = new byte[contents.length];
+        stream.readFully(read);
+        assertArrayEquals(contents, read, "The read path should not depend on 
the optional getScheme()");
+      }
+    }
+  }
+
+  @Test
+  public void testGetSchemeFallsBackToTheUriWhenUnimplemented() throws 
IOException {
+    try (FileSystem localFs = FileSystem.newInstanceLocal(new 
Configuration())) {
+      assertEquals("file", HadoopFSUtils.getScheme(localFs),
+          "LocalFileSystem overrides getScheme(), so the helper should return 
what it reports "
+              + "rather than falling back to getUri()");
+
+      try (FileSystem noScheme = new FilterFileSystem(localFs)) {
+        assertThrows(UnsupportedOperationException.class, noScheme::getScheme);
+        assertEquals("file", HadoopFSUtils.getScheme(noScheme),
+            "FilterFileSystem does not override getScheme(), so the helper 
should fall back to "
+                + "getUri().getScheme()");
+      }

Review Comment:
   Applied. The nested block is gone and the comment about why 
`newInstanceLocal` is used now stands on its own:
   
   ```java
   // FilterFileSystem#close closes the delegate, so the wrapper is not given 
its own block: it owns
   // nothing, and closing it here would close localFs a second time.
   FileSystem noScheme = newFsWithoutGetScheme(localFs);
   ```
   
   Thanks for checking that the double close was harmless rather than just 
asserting it — you are right that the block implied ownership that does not 
exist.
   



##########
hudi-hadoop-common/src/test/java/org/apache/hudi/hadoop/fs/TestHadoopFSUtils.java:
##########
@@ -22,22 +22,80 @@
 import org.apache.hudi.storage.StoragePath;
 import org.apache.hudi.storage.StoragePathInfo;
 
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataInputStream;
 import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.FilterFileSystem;
 import org.apache.hadoop.fs.Path;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.ValueSource;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
 import static 
org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToHadoopFileStatus;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToHadoopPath;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToStoragePath;
 import static org.apache.hudi.hadoop.fs.HadoopFSUtils.convertToStoragePathInfo;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 /**
  * Tests {@link HadoopFSUtils}
  */
 public class TestHadoopFSUtils {
+  /**
+   * HUDI-4602: {@link FileSystem#getScheme()} is optional in Hadoop -- the 
base implementation throws
+   * {@link UnsupportedOperationException} -- and proxy implementations such 
as Presto's
+   * {@code PrestoS3FileSystem} do not override it. Opening a log file went 
straight through
+   * {@code isGCSFileSystem}, so a MOR {@code _rt} query on Presto failed with
+   * "Not implemented by the PrestoS3FileSystem FileSystem implementation" 
rather than reading anything.
+   *
+   * <p>{@link FilterFileSystem} has the same shape: it leaves {@code 
getScheme()} to the throwing base
+   * implementation while overriding {@code getUri()}.
+   */
+  @Test
+  public void testGetFSDataInputStreamWhenGetSchemeIsUnimplemented(@TempDir 
File tempDir) throws IOException {

Review Comment:
   Switched off `File`, with one compromise: this file also uses Hadoop's 
`Path` in `testPathConversion` and `testFileStatusConversion`, so the two 
cannot both be imported unqualified. I qualified the nio one at its four use 
sites rather than rewrite the pre-existing conversion tests to 
`org.apache.hadoop.fs.Path`:
   
   ```java
   public void testGetFSDataInputStreamWhenGetSchemeIsUnimplemented(@TempDir 
java.nio.file.Path tempDir)
   ```
   
   Verbose, but it keeps the diff to the tests this PR is actually about, and 
the `java.io.File` import is gone along with the `file.toPath()` round-trip. 
Happy to do the unqualified version and convert the Hadoop `Path` uses if you 
would prefer the file consistent.
   
   You were right that this needed `toURI()` → `toUri()` as well.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to