This is an automated email from the ASF dual-hosted git repository.

danny0405 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hudi.git


The following commit(s) were added to refs/heads/master by this push:
     new 8911aa2d3c7 [HUDI-7576] Improve efficiency of 
getRelativePartitionPath, reduce computation of partitionPath in 
AbstractTableFileSystemView (#11001)
8911aa2d3c7 is described below

commit 8911aa2d3c7dcc31263023c128f38d70a7b820d5
Author: Tim Brown <[email protected]>
AuthorDate: Fri May 3 17:37:10 2024 -0700

    [HUDI-7576] Improve efficiency of getRelativePartitionPath, reduce 
computation of partitionPath in AbstractTableFileSystemView (#11001)
---
 .../hudi/table/action/clean/CleanPlanner.java      |  2 +-
 .../table/action/commit/TestUpsertPartitioner.java |  4 +-
 .../java/org/apache/hudi/common/fs/FSUtils.java    |  9 ++-
 .../table/view/AbstractTableFileSystemView.java    | 83 +++++++++++-----------
 .../IncrementalTimelineSyncFileSystemView.java     |  6 +-
 .../org/apache/hudi/common/fs/TestFSUtils.java     | 45 +++++-------
 6 files changed, 66 insertions(+), 83 deletions(-)

diff --git 
a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanner.java
 
b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanner.java
index 9d1d1a0bc02..651ea401087 100644
--- 
a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanner.java
+++ 
b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanner.java
@@ -467,7 +467,7 @@ public class CleanPlanner<T, I, K, O> implements 
Serializable {
     try {
       HoodieTableFileSystemView fsView = new 
HoodieTableFileSystemView(hoodieTable.getMetaClient(), 
hoodieTable.getActiveTimeline());
       StoragePath fullPartitionPath = new 
StoragePath(hoodieTable.getMetaClient().getBasePathV2(), partitionPath);
-      fsView.addFilesToView(FSUtils.getAllDataFilesInPartition(
+      fsView.addFilesToView(partitionPath, FSUtils.getAllDataFilesInPartition(
           hoodieTable.getMetaClient().getStorage(), fullPartitionPath));
       // use #getAllFileGroups(partitionPath) instead of #getAllFileGroups() 
to exclude the replaced file groups.
       return fsView.getAllFileGroups(partitionPath).findAny().isPresent();
diff --git 
a/hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/table/action/commit/TestUpsertPartitioner.java
 
b/hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/table/action/commit/TestUpsertPartitioner.java
index e3205219248..c9228375a72 100644
--- 
a/hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/table/action/commit/TestUpsertPartitioner.java
+++ 
b/hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/table/action/commit/TestUpsertPartitioner.java
@@ -469,9 +469,9 @@ public class TestUpsertPartitioner extends 
HoodieClientTestBase {
     assertEquals(3, partitioner.numPartitions());
     assertEquals(
         Arrays.asList(
-            new BucketInfo(BucketType.UPDATE, "fg-1", partitionPath),
+            new BucketInfo(BucketType.UPDATE, "fg-3", partitionPath),
             new BucketInfo(BucketType.UPDATE, "fg-2", partitionPath),
-            new BucketInfo(BucketType.UPDATE, "fg-3", partitionPath)
+            new BucketInfo(BucketType.UPDATE, "fg-1", partitionPath)
         ),
         partitioner.getBucketInfos());
   }
diff --git a/hudi-common/src/main/java/org/apache/hudi/common/fs/FSUtils.java 
b/hudi-common/src/main/java/org/apache/hudi/common/fs/FSUtils.java
index b0c6da3c96d..431ad474a02 100644
--- a/hudi-common/src/main/java/org/apache/hudi/common/fs/FSUtils.java
+++ b/hudi-common/src/main/java/org/apache/hudi/common/fs/FSUtils.java
@@ -234,17 +234,16 @@ public class FSUtils {
     fullPartitionPath = getPathWithoutSchemeAndAuthority(fullPartitionPath);
 
     String fullPartitionPathStr = fullPartitionPath.toString();
+    String basePathString = basePath.toString();
 
-    if (!fullPartitionPathStr.startsWith(basePath.toString())) {
+    if (!fullPartitionPathStr.startsWith(basePathString)) {
       throw new IllegalArgumentException("Partition path \"" + 
fullPartitionPathStr
           + "\" does not belong to base-path \"" + basePath + "\"");
     }
 
-    int partitionStartIndex = fullPartitionPathStr.indexOf(basePath.getName(),
-        basePath.getParent() == null ? 0 : 
basePath.getParent().toString().length());
     // Partition-Path could be empty for non-partitioned tables
-    return partitionStartIndex + basePath.getName().length() == 
fullPartitionPathStr.length() ? ""
-        : fullPartitionPathStr.substring(partitionStartIndex + 
basePath.getName().length() + 1);
+    return fullPartitionPathStr.length() == basePathString.length() ? ""
+        : fullPartitionPathStr.substring(basePathString.length() + 1);
   }
 
   public static StoragePath getPathWithoutSchemeAndAuthority(StoragePath path) 
{
diff --git 
a/hudi-common/src/main/java/org/apache/hudi/common/table/view/AbstractTableFileSystemView.java
 
b/hudi-common/src/main/java/org/apache/hudi/common/table/view/AbstractTableFileSystemView.java
index c3a7906ee9f..7d656ee988d 100644
--- 
a/hudi-common/src/main/java/org/apache/hudi/common/table/view/AbstractTableFileSystemView.java
+++ 
b/hudi-common/src/main/java/org/apache/hudi/common/table/view/AbstractTableFileSystemView.java
@@ -109,10 +109,6 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
 
   private BootstrapIndex bootstrapIndex;
 
-  private String getPartitionPathFor(HoodieBaseFile baseFile) {
-    return FSUtils.getRelativePartitionPath(metaClient.getBasePathV2(), 
baseFile.getStoragePath().getParent());
-  }
-
   /**
    * Initialize the view.
    */
@@ -158,10 +154,21 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
 
   /**
    * Adds the provided statuses into the file system view, and also caches it 
inside this object.
+   * If the file statuses are limited to a single partition, use {@link 
#addFilesToView(String, List)} instead.
    */
   public List<HoodieFileGroup> addFilesToView(List<StoragePathInfo> statuses) {
+    Map<String, List<StoragePathInfo>> statusesByPartitionPath = 
statuses.stream()
+        .collect(Collectors.groupingBy(fileStatus -> 
FSUtils.getRelativePartitionPath(metaClient.getBasePathV2(), 
fileStatus.getPath().getParent())));
+    return statusesByPartitionPath.entrySet().stream().map(entry -> 
addFilesToView(entry.getKey(), entry.getValue()))
+        .flatMap(List::stream).collect(Collectors.toList());
+  }
+
+  /**
+   * Adds the provided statuses into the file system view for a single 
partition, and also caches it inside this object.
+   */
+  public List<HoodieFileGroup> addFilesToView(String partitionPath, 
List<StoragePathInfo> statuses) {
     HoodieTimer timer = HoodieTimer.start();
-    List<HoodieFileGroup> fileGroups = buildFileGroups(statuses, 
visibleCommitsAndCompactionTimeline, true);
+    List<HoodieFileGroup> fileGroups = buildFileGroups(partitionPath, 
statuses, visibleCommitsAndCompactionTimeline, true);
     long fgBuildTimeTakenMs = timer.endTimer();
     timer.startTimer();
     // Group by partition for efficient updates for both InMemory and 
DiskBased structures.
@@ -191,37 +198,28 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
   /**
    * Build FileGroups from passed in file-status.
    */
-  protected List<HoodieFileGroup> buildFileGroups(List<StoragePathInfo> 
statuses, HoodieTimeline timeline,
+  protected List<HoodieFileGroup> buildFileGroups(String partition, 
List<StoragePathInfo> statuses, HoodieTimeline timeline,
                                                   boolean 
addPendingCompactionFileSlice) {
-    return buildFileGroups(convertFileStatusesToBaseFiles(statuses), 
convertFileStatusesToLogFiles(statuses),
+    return buildFileGroups(partition, 
convertFileStatusesToBaseFiles(statuses), 
convertFileStatusesToLogFiles(statuses),
         timeline,
         addPendingCompactionFileSlice);
   }
 
-  protected List<HoodieFileGroup> buildFileGroups(Stream<HoodieBaseFile> 
baseFileStream,
+  protected List<HoodieFileGroup> buildFileGroups(String partition, 
Stream<HoodieBaseFile> baseFileStream,
                                                   Stream<HoodieLogFile> 
logFileStream, HoodieTimeline timeline, boolean addPendingCompactionFileSlice) {
-    Map<Pair<String, String>, List<HoodieBaseFile>> baseFiles =
-        baseFileStream.collect(Collectors.groupingBy(baseFile -> {
-          String partitionPathStr = getPartitionPathFor(baseFile);
-          return Pair.of(partitionPathStr, baseFile.getFileId());
-        }));
-
-    Map<Pair<String, String>, List<HoodieLogFile>> logFiles = 
logFileStream.collect(Collectors.groupingBy((logFile) -> {
-      String partitionPathStr =
-          FSUtils.getRelativePartitionPath(metaClient.getBasePathV2(), 
logFile.getPath().getParent());
-      return Pair.of(partitionPathStr, logFile.getFileId());
-    }));
-
-    Set<Pair<String, String>> fileIdSet = new HashSet<>(baseFiles.keySet());
+    Map<String, List<HoodieBaseFile>> baseFiles =
+        
baseFileStream.collect(Collectors.groupingBy(HoodieBaseFile::getFileId));
+
+    Map<String, List<HoodieLogFile>> logFiles = 
logFileStream.collect(Collectors.groupingBy(HoodieLogFile::getFileId));
+
+    Set<String> fileIdSet = new HashSet<>(baseFiles.keySet());
     fileIdSet.addAll(logFiles.keySet());
 
-    List<HoodieFileGroup> fileGroups = new ArrayList<>();
-    fileIdSet.forEach(pair -> {
-      String fileId = pair.getValue();
-      String partitionPath = pair.getKey();
-      HoodieFileGroup group = new HoodieFileGroup(partitionPath, fileId, 
timeline);
-      if (baseFiles.containsKey(pair)) {
-        baseFiles.get(pair).forEach(group::addBaseFile);
+    List<HoodieFileGroup> fileGroups = new ArrayList<>(fileIdSet.size());
+    fileIdSet.forEach(fileId -> {
+      HoodieFileGroup group = new HoodieFileGroup(partition, fileId, timeline);
+      if (baseFiles.containsKey(fileId)) {
+        baseFiles.get(fileId).forEach(group::addBaseFile);
       }
       if (addPendingCompactionFileSlice) {
         // pending compaction file slice must be added before log files so that
@@ -235,8 +233,8 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
           group.addNewFileSliceAtInstant(pendingCompaction.get().getKey());
         }
       }
-      if (logFiles.containsKey(pair)) {
-        
logFiles.get(pair).stream().sorted(HoodieLogFile.getLogFileComparator()).forEach(logFile
 -> group.addLogFile(completionTimeQueryView, logFile));
+      if (logFiles.containsKey(fileId)) {
+        
logFiles.get(fileId).stream().sorted(HoodieLogFile.getLogFileComparator()).forEach(logFile
 -> group.addLogFile(completionTimeQueryView, logFile));
       }
       fileGroups.add(group);
     });
@@ -379,9 +377,9 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
           LOG.debug("Time taken to list partitions " + partitionSet + " =" + 
(endLsTs - beginLsTs));
           pathInfoMap.forEach((partitionPair, statuses) -> {
             String relativePartitionStr = partitionPair.getLeft();
-            List<HoodieFileGroup> groups = addFilesToView(statuses);
+            List<HoodieFileGroup> groups = 
addFilesToView(relativePartitionStr, statuses);
             if (groups.isEmpty()) {
-              storePartitionView(relativePartitionStr, new ArrayList<>());
+              storePartitionView(relativePartitionStr, 
Collections.emptyList());
             }
             LOG.debug("#files found in partition (" + relativePartitionStr + 
") =" + statuses.size());
           });
@@ -469,7 +467,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
         // Not loaded yet
         try {
           LOG.info("Building file system view for partition (" + 
partitionPathStr + ")");
-          List<HoodieFileGroup> groups = 
addFilesToView(getAllFilesInPartition(partitionPathStr));
+          List<HoodieFileGroup> groups = addFilesToView(partitionPathStr, 
getAllFilesInPartition(partitionPathStr));
           if (groups.isEmpty()) {
             storePartitionView(partitionPathStr, new ArrayList<>());
           }
@@ -541,11 +539,10 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
    * With async compaction, it is possible to see partial/complete base-files 
due to inflight-compactions, Ignore those
    * base-files.
    *
+   * @param partitionPath partition path for the base file
    * @param baseFile base File
    */
-  protected boolean isBaseFileDueToPendingCompaction(HoodieBaseFile baseFile) {
-    final String partitionPath = getPartitionPathFor(baseFile);
-
+  protected boolean isBaseFileDueToPendingCompaction(String partitionPath, 
HoodieBaseFile baseFile) {
     Option<Pair<String, CompactionOperation>> compactionWithInstantTime =
         getPendingCompactionOperationWithInstant(new 
HoodieFileGroupId(partitionPath, baseFile.getFileId()));
     return (compactionWithInstantTime.isPresent()) && (null != 
compactionWithInstantTime.get().getKey())
@@ -745,7 +742,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
         .map(fileGroup -> Option.fromJavaOptional(fileGroup.getAllBaseFiles()
             .filter(baseFile -> 
HoodieTimeline.compareTimestamps(baseFile.getCommitTime(), 
HoodieTimeline.LESSER_THAN_OR_EQUALS, maxCommitTime
             ))
-            .filter(df -> !isBaseFileDueToPendingCompaction(df) && 
!isBaseFileDueToPendingClustering(df)).findFirst()))
+            .filter(df -> !isBaseFileDueToPendingCompaction(partitionPath, df) 
&& !isBaseFileDueToPendingClustering(df)).findFirst()))
         .filter(Option::isPresent).map(Option::get)
         .map(df -> addBootstrapBaseFileIfPresent(new 
HoodieFileGroupId(partitionPath, df.getFileId()), df));
   }
@@ -761,7 +758,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
       } else {
         return fetchHoodieFileGroup(partitionPath, fileId).map(fileGroup -> 
fileGroup.getAllBaseFiles()
                 .filter(baseFile -> 
HoodieTimeline.compareTimestamps(baseFile.getCommitTime(), 
HoodieTimeline.EQUALS,
-                    instantTime)).filter(df -> 
!isBaseFileDueToPendingCompaction(df) && 
!isBaseFileDueToPendingClustering(df)).findFirst().orElse(null))
+                    instantTime)).filter(df -> 
!isBaseFileDueToPendingCompaction(partitionPath, df) && 
!isBaseFileDueToPendingClustering(df)).findFirst().orElse(null))
             .map(df -> addBootstrapBaseFileIfPresent(new 
HoodieFileGroupId(partitionPath, fileId), df));
       }
     } finally {
@@ -797,7 +794,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
           .filter(fileGroup -> 
!isFileGroupReplacedBeforeAny(fileGroup.getFileGroupId(), commitsToReturn))
           .map(fileGroup -> Pair.of(fileGroup.getFileGroupId(), 
Option.fromJavaOptional(
               fileGroup.getAllBaseFiles().filter(baseFile -> 
commitsToReturn.contains(baseFile.getCommitTime())
-                  && !isBaseFileDueToPendingCompaction(baseFile) && 
!isBaseFileDueToPendingClustering(baseFile)).findFirst()))).filter(p -> 
p.getValue().isPresent())
+                  && 
!isBaseFileDueToPendingCompaction(fileGroup.getPartitionPath(), baseFile) && 
!isBaseFileDueToPendingClustering(baseFile)).findFirst()))).filter(p -> 
p.getValue().isPresent())
           .map(p -> addBootstrapBaseFileIfPresent(p.getKey(), 
p.getValue().get()));
     } finally {
       readLock.unlock();
@@ -833,7 +830,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
       return fetchAllBaseFiles(partitionPath)
           .filter(df -> !isFileGroupReplaced(partitionPath, df.getFileId()))
           .filter(df -> 
visibleCommitsAndCompactionTimeline.containsOrBeforeTimelineStarts(df.getCommitTime()))
-          .filter(df -> !isBaseFileDueToPendingCompaction(df) && 
!isBaseFileDueToPendingClustering(df))
+          .filter(df -> !isBaseFileDueToPendingCompaction(partitionPath, df) 
&& !isBaseFileDueToPendingClustering(df))
           .map(df -> addBootstrapBaseFileIfPresent(new 
HoodieFileGroupId(partitionPath, df.getFileId()), df));
     } finally {
       readLock.unlock();
@@ -875,7 +872,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
       return getLatestFileSlices(partition);
     } else {
       try {
-        Stream<FileSlice> fileSliceStream = 
buildFileGroups(getAllFilesInPartition(partition), 
visibleCommitsAndCompactionTimeline, true).stream()
+        Stream<FileSlice> fileSliceStream = buildFileGroups(partition, 
getAllFilesInPartition(partition), visibleCommitsAndCompactionTimeline, 
true).stream()
             .filter(fg -> !isFileGroupReplaced(fg))
             .map(HoodieFileGroup::getLatestFileSlice)
             .filter(Option::isPresent).map(Option::get)
@@ -1090,7 +1087,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
       return getAllFileGroups(partition);
     } else {
       try {
-        Stream<HoodieFileGroup> fileGroupStream = 
buildFileGroups(getAllFilesInPartition(partition), 
visibleCommitsAndCompactionTimeline, true).stream()
+        Stream<HoodieFileGroup> fileGroupStream = buildFileGroups(partition, 
getAllFilesInPartition(partition), visibleCommitsAndCompactionTimeline, 
true).stream()
             .filter(fg -> !isFileGroupReplaced(fg));
         if (bootstrapIndex.useIndex()) {
           final Map<HoodieFileGroupId, BootstrapBaseFileMapping> 
bootstrapBaseFileMappings = getBootstrapBaseFileMappings(partition);
@@ -1430,7 +1427,7 @@ public abstract class AbstractTableFileSystemView 
implements SyncableFileSystemV
 
   protected Option<HoodieBaseFile> getLatestBaseFile(HoodieFileGroup 
fileGroup) {
     return Option
-        .fromJavaOptional(fileGroup.getAllBaseFiles().filter(df -> 
!isBaseFileDueToPendingCompaction(df) && 
!isBaseFileDueToPendingClustering(df)).findFirst());
+        .fromJavaOptional(fileGroup.getAllBaseFiles().filter(df -> 
!isBaseFileDueToPendingCompaction(fileGroup.getPartitionPath(), df) && 
!isBaseFileDueToPendingClustering(df)).findFirst());
   }
 
   /**
diff --git 
a/hudi-common/src/main/java/org/apache/hudi/common/table/view/IncrementalTimelineSyncFileSystemView.java
 
b/hudi-common/src/main/java/org/apache/hudi/common/table/view/IncrementalTimelineSyncFileSystemView.java
index d4e7fbfd1fd..dead4f0c726 100644
--- 
a/hudi-common/src/main/java/org/apache/hudi/common/table/view/IncrementalTimelineSyncFileSystemView.java
+++ 
b/hudi-common/src/main/java/org/apache/hudi/common/table/view/IncrementalTimelineSyncFileSystemView.java
@@ -273,7 +273,7 @@ public abstract class IncrementalTimelineSyncFileSystemView 
extends AbstractTabl
                 p.getFileSizeInBytes(), false, (short) 0, 0, 0))
             .collect(Collectors.toList());
         List<HoodieFileGroup> fileGroups =
-            buildFileGroups(pathInfoList, 
timeline.filterCompletedAndCompactionInstants(), false);
+            buildFileGroups(partition, pathInfoList, 
timeline.filterCompletedAndCompactionInstants(), false);
         applyDeltaFileSlicesToPartitionView(partition, fileGroups, 
DeltaApplyMode.ADD);
       } else {
         LOG.warn("Skipping partition (" + partition + ") when syncing instant 
(" + instant + ") as it is not loaded");
@@ -382,7 +382,7 @@ public abstract class IncrementalTimelineSyncFileSystemView 
extends AbstractTabl
           .map(p -> new StoragePathInfo(new StoragePath(p), 0, false, (short) 
0, 0, 0))
           .collect(Collectors.toList());
       List<HoodieFileGroup> fileGroups =
-          buildFileGroups(pathInfoList, 
timeline.filterCompletedAndCompactionInstants(), false);
+          buildFileGroups(partition, pathInfoList, 
timeline.filterCompletedAndCompactionInstants(), false);
       applyDeltaFileSlicesToPartitionView(partition, fileGroups, 
DeltaApplyMode.REMOVE);
     } else {
       LOG.warn("Skipping partition (" + partition + ") when syncing instant (" 
+ instant + ") as it is not loaded");
@@ -451,7 +451,7 @@ public abstract class IncrementalTimelineSyncFileSystemView 
extends AbstractTabl
 
     HoodieTimeline timeline = deltaFileGroups.stream().map(df -> 
df.getTimeline()).findAny().get();
     List<HoodieFileGroup> fgs =
-        buildFileGroups(viewDataFiles.values().stream(), 
viewLogFiles.values().stream(), timeline, true);
+        buildFileGroups(partition, viewDataFiles.values().stream(), 
viewLogFiles.values().stream(), timeline, true);
     storePartitionView(partition, fgs);
   }
 
diff --git 
a/hudi-common/src/test/java/org/apache/hudi/common/fs/TestFSUtils.java 
b/hudi-common/src/test/java/org/apache/hudi/common/fs/TestFSUtils.java
index 07b21db6cc1..b3949f46895 100644
--- a/hudi-common/src/test/java/org/apache/hudi/common/fs/TestFSUtils.java
+++ b/hudi-common/src/test/java/org/apache/hudi/common/fs/TestFSUtils.java
@@ -46,6 +46,8 @@ import 
org.junit.contrib.java.lang.system.EnvironmentVariables;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -204,35 +206,20 @@ public class TestFSUtils extends HoodieCommonTestHarness {
     assertThrows(IllegalArgumentException.class, () -> 
FSUtils.getRelativePartitionPath(basePath, nonPartitionPath));
   }
 
-  @Test
-  public void testGetRelativePartitionPathWithStoragePath() {
-    StoragePath basePath = new StoragePath("/test/apache");
-    StoragePath partitionPath = new StoragePath("/test/apache/hudi/sub");
-    assertEquals("hudi/sub", FSUtils.getRelativePartitionPath(basePath, 
partitionPath));
-
-    StoragePath nonPartitionPath = new StoragePath("/test/something/else");
-    assertThrows(IllegalArgumentException.class, () -> 
FSUtils.getRelativePartitionPath(basePath, nonPartitionPath));
-  }
-
-  @Test
-  public void testGetRelativePartitionPathSameFolder() {
-    Path basePath = new Path("/test");
-    Path partitionPath = new Path("/test");
-    assertEquals("", FSUtils.getRelativePartitionPath(basePath, 
partitionPath));
-  }
-
-  @Test
-  public void testGetRelativePartitionPathRepeatedFolderNameBasePath() {
-    Path basePath = new Path("/test/apache/apache");
-    Path partitionPath = new Path("/test/apache/apache/hudi");
-    assertEquals("hudi", FSUtils.getRelativePartitionPath(basePath, 
partitionPath));
-  }
-
-  @Test
-  public void testGetRelativePartitionPathRepeatedFolderNamePartitionPath() {
-    Path basePath = new Path("/test/apache");
-    Path partitionPath = new Path("/test/apache/apache/hudi");
-    assertEquals("apache/hudi", FSUtils.getRelativePartitionPath(basePath, 
partitionPath));
+  @ParameterizedTest
+  @CsvSource({
+      "/test,/test,",
+      "s3://test,s3://test,",
+      "s3://test/foo,s3://test/foo,",
+      "/test/foo,/test/foo,",
+      "/test/apache/apache,/test/apache/apache/hudi,hudi",
+      "/test/apache,/test/apache/hudi,hudi",
+      "s3://test/apache,s3://test/apache/apache/hudi,apache/hudi"})
+  public void testGetRelativePartitionPath(String basePathStr, String 
partitionPathStr, String expected) {
+    StoragePath basePath = new StoragePath(basePathStr);
+    StoragePath partitionPath = new StoragePath(partitionPathStr);
+    String result = FSUtils.getRelativePartitionPath(basePath, partitionPath);
+    assertEquals(expected == null ? "" : expected, result);
   }
 
   @Test

Reply via email to