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

anujmodi pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 8f78af1edcd HADOOP-19580. [ABFS][BugFix] IsNonEmptyDirectory Check 
should loop on listing using updated continuation token (#7716)
8f78af1edcd is described below

commit 8f78af1edcd9ef9ce67212ff7dd76e4484a846c3
Author: Anuj Modi <anujmodi2...@gmail.com>
AuthorDate: Wed May 28 23:53:13 2025 +0530

    HADOOP-19580. [ABFS][BugFix] IsNonEmptyDirectory Check should loop on 
listing using updated continuation token (#7716)
    
    Contributed by Anuj Modi
    Reviewed by Sneha Vijayarajan
---
 .../fs/azurebfs/services/AbfsBlobClient.java       |  2 +-
 .../ITestAzureBlobFileSystemListStatus.java        | 44 ++++++++++++++++++----
 .../fs/azurebfs/services/ITestAbfsClient.java      | 42 +++++++++++++++++++--
 3 files changed, 76 insertions(+), 12 deletions(-)

diff --git 
a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsBlobClient.java
 
b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsBlobClient.java
index 5d8c2efb94e..a0567da97b2 100644
--- 
a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsBlobClient.java
+++ 
b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsBlobClient.java
@@ -2037,7 +2037,7 @@ public boolean isNonEmptyDirectory(String path,
     List<FileStatus> fileStatusList = new ArrayList<>();
     // We need to loop on continuation token until we get an entry or 
continuation token becomes null.
     do {
-      ListResponseData listResponseData = listPath(path, false, 1, null, 
tracingContext, null);
+      ListResponseData listResponseData = listPath(path, false, 1, 
continuationToken, tracingContext, null);
       fileStatusList.addAll(listResponseData.getFileStatusList());
       continuationToken = listResponseData.getContinuationToken();
     } while (StringUtils.isNotEmpty(continuationToken) && 
fileStatusList.isEmpty());
diff --git 
a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAzureBlobFileSystemListStatus.java
 
b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAzureBlobFileSystemListStatus.java
index a533f352a97..e491362df5c 100644
--- 
a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAzureBlobFileSystemListStatus.java
+++ 
b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAzureBlobFileSystemListStatus.java
@@ -391,9 +391,9 @@ public void testEmptyListingInSubsequentCall() throws 
IOException {
         true, 2, 0);
     testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN, true, 
EMPTY_STRING,
         false, 2, 1);
-    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN, true, 
TEST_CONTINUATION_TOKEN,
+    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN + 1, 
true, TEST_CONTINUATION_TOKEN + 2,
         true, 3, 0);
-    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN, true, 
TEST_CONTINUATION_TOKEN,
+    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN + 1, 
true, TEST_CONTINUATION_TOKEN + 2,
         false, 3, 1);
 
     testEmptyListingInSubsequentCallInternal(EMPTY_STRING, false, EMPTY_STRING,
@@ -409,9 +409,9 @@ public void testEmptyListingInSubsequentCall() throws 
IOException {
         true, 2, 1);
     testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN, false, 
EMPTY_STRING,
         false, 2, 2);
-    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN, false, 
TEST_CONTINUATION_TOKEN,
+    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN + 1, 
false, TEST_CONTINUATION_TOKEN + 2,
         true, 3, 1);
-    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN, false, 
TEST_CONTINUATION_TOKEN,
+    testEmptyListingInSubsequentCallInternal(TEST_CONTINUATION_TOKEN + 1, 
false, TEST_CONTINUATION_TOKEN + 2,
         false, 3, 2);
   }
 
@@ -453,9 +453,23 @@ private void 
testEmptyListingInSubsequentCallInternal(String firstCT,
     listResponseData3.setFileStatusList(new ArrayList<>());
     listResponseData3.setOp(Mockito.mock(AbfsRestOperation.class));
 
-    
Mockito.doReturn(listResponseData1).doReturn(listResponseData2).doReturn(listResponseData3)
-        .when(spiedClient).listPath(eq("/testPath"), eq(false), eq(1),
-        any(), any(), any());
+    final int[] itr = new int[1];
+    final String[] continuationTokenUsed = new String[3];
+
+    Mockito.doAnswer(invocationOnMock -> {
+      if (itr[0] == 0) {
+        itr[0]++;
+        continuationTokenUsed[0] = invocationOnMock.getArgument(3);
+        return listResponseData1;
+      } else if (itr[0] == 1) {
+        itr[0]++;
+        continuationTokenUsed[1] = invocationOnMock.getArgument(3);
+        return listResponseData2;
+      }
+      continuationTokenUsed[2] = invocationOnMock.getArgument(3);
+      return listResponseData3;
+    }).when(spiedClient).listPath(eq("/testPath"), eq(false), eq(1),
+        any(), any(TracingContext.class), any());
 
     FileStatus[] list = spiedFs.listStatus(new Path("/testPath"));
 
@@ -473,6 +487,22 @@ private void 
testEmptyListingInSubsequentCallInternal(String firstCT,
       Mockito.verify(spiedClient, times(0))
           .getPathStatus(eq("/testPath"), any(), eq(null), eq(false));
     }
+
+    Assertions.assertThat(continuationTokenUsed[0])
+        .describedAs("First continuation token used is not as expected")
+        .isNull();
+
+    if (expectedInvocations > 1) {
+      Assertions.assertThat(continuationTokenUsed[1])
+          .describedAs("Second continuation token used is not as expected")
+          .isEqualTo(firstCT);
+    }
+
+    if (expectedInvocations > 2) {
+      Assertions.assertThat(continuationTokenUsed[2])
+          .describedAs("Third continuation token used is not as expected")
+          .isEqualTo(secondCT);
+    }
   }
 
   /**
diff --git 
a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/ITestAbfsClient.java
 
b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/ITestAbfsClient.java
index 1083df3ba57..cba1643478f 100644
--- 
a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/ITestAbfsClient.java
+++ 
b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/services/ITestAbfsClient.java
@@ -745,18 +745,18 @@ public void testIsNonEmptyDirectory() throws IOException {
         true, 2, false);
     testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN, true, 
EMPTY_STRING,
         false, 2, true);
-    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN, true, 
TEST_CONTINUATION_TOKEN,
+    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN + 1, true, 
TEST_CONTINUATION_TOKEN + 2,
         true, 3, false);
-    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN, true, 
TEST_CONTINUATION_TOKEN,
+    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN + 1, true, 
TEST_CONTINUATION_TOKEN + 2,
         false, 2, true);
 
     testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN, false, 
EMPTY_STRING,
         true, 1, true);
     testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN, false, 
EMPTY_STRING,
         false, 1, true);
-    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN, false, 
TEST_CONTINUATION_TOKEN,
+    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN + 1, false, 
TEST_CONTINUATION_TOKEN + 2,
         true, 1, true);
-    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN, false, 
TEST_CONTINUATION_TOKEN,
+    testIsNonEmptyDirectoryInternal(TEST_CONTINUATION_TOKEN + 1, false, 
TEST_CONTINUATION_TOKEN + 2,
         false, 1, true);
   }
 
@@ -801,11 +801,45 @@ private void testIsNonEmptyDirectoryInternal(String 
firstCT,
         .when(spiedClient).listPath(eq("/testPath"), eq(false), eq(1),
             any(), any(), any());
 
+    final int[] itr = new int[1];
+    final String[] continuationTokenUsed = new String[3];
+
+    Mockito.doAnswer(invocationOnMock -> {
+      if (itr[0] == 0) {
+        itr[0]++;
+        continuationTokenUsed[0] = invocationOnMock.getArgument(3);
+        return listResponseData1;
+      } else if (itr[0] == 1) {
+        itr[0]++;
+        continuationTokenUsed[1] = invocationOnMock.getArgument(3);
+        return listResponseData2;
+      }
+      continuationTokenUsed[2] = invocationOnMock.getArgument(3);
+      return listResponseData3;
+    }).when(spiedClient).listPath(eq("/testPath"), eq(false), eq(1),
+        any(), any(TracingContext.class), any());
+
     Assertions.assertThat(spiedClient.isNonEmptyDirectory("/testPath",
         Mockito.mock(TracingContext.class)))
         .describedAs("isNonEmptyDirectory in client giving unexpected results")
         .isEqualTo(isNonEmpty);
 
+    Assertions.assertThat(continuationTokenUsed[0])
+        .describedAs("First continuation token used is not as expected")
+        .isNull();
+
+    if (expectedInvocations > 1) {
+      Assertions.assertThat(continuationTokenUsed[1])
+          .describedAs("Second continuation token used is not as expected")
+          .isEqualTo(firstCT);
+    }
+
+    if (expectedInvocations > 2) {
+      Assertions.assertThat(continuationTokenUsed[2])
+          .describedAs("Third continuation token used is not as expected")
+          .isEqualTo(secondCT);
+    }
+
     Mockito.verify(spiedClient, times(expectedInvocations))
         .listPath(eq("/testPath"), eq(false), eq(1),
             any(), any(TracingContext.class), any());


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to