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

bamaer pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 64c64e9dca Fix Create folder validation to check folderName and reject 
a blank name (#8908)
64c64e9dca is described below

commit 64c64e9dca92a903c2fe6a6db0703636d93668d2
Author: Lance <[email protected]>
AuthorDate: Wed Oct 14 18:54:26 2026 +0800

    Fix Create folder validation to check folderName and reject a blank name 
(#8908)
    
    Signed-off-by: leehaut <[email protected]>
---
 .../actions/createfolder/ActionCreateFolder.java   |  44 +----
 .../createfolder/ActionCreateFolderTest.java       | 182 +++++++++++++++++++++
 2 files changed, 188 insertions(+), 38 deletions(-)

diff --git 
a/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
 
b/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
index 8d78d71b59..66febf230b 100644
--- 
a/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
+++ 
b/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
@@ -18,6 +18,8 @@
 package org.apache.hop.workflow.actions.createfolder;
 
 import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.vfs2.FileObject;
 import org.apache.commons.vfs2.FileType;
@@ -40,6 +42,8 @@ import 
org.apache.hop.workflow.action.validator.ValidatorContext;
  * This defines a 'create folder' action. Its main use would be to create 
empty folder that can be
  * used to control the flow in ETL cycles.
  */
+@Getter
+@Setter
 @Action(
     id = "CREATE_FOLDER",
     name = "i18n::ActionCreateFolder.Name",
@@ -136,48 +140,12 @@ public class ActionCreateFolder extends ActionBase 
implements Cloneable, IAction
     AbstractFileValidator.putVariableSpace(ctx, getVariables());
     AndValidator.putValidators(
         ctx,
-        ActionValidatorUtils.notNullValidator(),
+        ActionValidatorUtils.notBlankValidator(),
         ActionValidatorUtils.fileDoesNotExistValidator());
-    ActionValidatorUtils.andValidator().validate(this, "filename", remarks, 
ctx);
+    ActionValidatorUtils.andValidator().validate(this, "folderName", remarks, 
ctx);
   }
 
   public String getRealFolderName() {
     return resolve(getFolderName());
   }
-
-  /**
-   * Gets folderName
-   *
-   * @return value of folderName
-   */
-  public String getFolderName() {
-    return folderName;
-  }
-
-  /**
-   * Sets folderName
-   *
-   * @param folderName value of folderName
-   */
-  public void setFolderName(String folderName) {
-    this.folderName = folderName;
-  }
-
-  /**
-   * Gets failIfFolderExists
-   *
-   * @return value of failIfFolderExists
-   */
-  public boolean isFailIfFolderExists() {
-    return failIfFolderExists;
-  }
-
-  /**
-   * Sets failIfFolderExists
-   *
-   * @param failIfFolderExists value of failIfFolderExists
-   */
-  public void setFailIfFolderExists(boolean failIfFolderExists) {
-    this.failIfFolderExists = failIfFolderExists;
-  }
 }
diff --git 
a/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
 
b/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
index 0d124cf312..9813e4faac 100644
--- 
a/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
+++ 
b/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
@@ -19,13 +19,32 @@
 package org.apache.hop.workflow.actions.createfolder;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.Result;
+import org.apache.hop.core.logging.HopLogStore;
 import org.apache.hop.workflow.action.ActionSerializationTestUtil;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 
+/** Unit test for {@link ActionCreateFolder} */
 class ActionCreateFolderTest {
 
+  @TempDir Path tempDir;
+
+  @BeforeAll
+  static void setUpBeforeClass() {
+    HopLogStore.init();
+  }
+
   @Test
   void testSerialization() throws Exception {
     ActionCreateFolder action =
@@ -35,4 +54,167 @@ class ActionCreateFolderTest {
     assertEquals("${TEST_FOLDER}/one", action.getFolderName());
     assertTrue(action.isFailIfFolderExists());
   }
+
+  @Test
+  void testClone() throws Exception {
+    ActionCreateFolder action =
+        ActionSerializationTestUtil.testSerialization(
+            "/create-folder-action.xml", ActionCreateFolder.class);
+
+    ActionCreateFolder clone = (ActionCreateFolder) action.clone();
+
+    assertEquals(action.getFolderName(), clone.getFolderName());
+    assertEquals(action.isFailIfFolderExists(), clone.isFailIfFolderExists());
+  }
+
+  @Test
+  void constructorLeavesFolderNameEmptyAndFailsIfItExists() {
+    ActionCreateFolder action = new ActionCreateFolder();
+
+    assertNull(action.getFolderName());
+    assertTrue(action.isFailIfFolderExists());
+    assertTrue(action.isEvaluation());
+  }
+
+  @Test
+  void getRealFolderNameResolvesVariables() {
+    ActionCreateFolder action = new ActionCreateFolder();
+    action.setVariable("TEST_FOLDER", tempDir.toString());
+    action.setFolderName("${TEST_FOLDER}/one");
+
+    assertEquals(tempDir.toString() + "/one", action.getRealFolderName());
+  }
+
+  @Test
+  void checkAcceptsAFolderName() {
+    ActionCreateFolder action = new ActionCreateFolder();
+    action.setFolderName(tempDir.resolve("missing").toString());
+
+    List<ICheckResult> remarks = check(action);
+
+    assertTrue(errors(remarks).isEmpty());
+    assertTrue(remarks.stream().anyMatch(remark -> 
remark.getText().contains("folderName is OK")));
+    assertTrue(remarks.stream().noneMatch(remark -> 
remark.getText().contains("Reason: filename")));
+  }
+
+  @Test
+  void checkReportsAMissingFolderName() {
+    ActionCreateFolder action = new ActionCreateFolder();
+
+    List<String> errors = errors(check(action));
+
+    assertEquals(1, errors.size());
+    assertTrue(errors.getFirst().contains("folderName cannot be null or 
blank"));
+    assertFalse(errors.getFirst().contains("Reason: filename"));
+  }
+
+  @Test
+  void checkReportsAnEmptyFolderName() {
+    ActionCreateFolder action = new ActionCreateFolder();
+    action.setFolderName("");
+
+    List<String> errors = errors(check(action));
+
+    assertEquals(1, errors.size());
+    assertTrue(errors.getFirst().contains("folderName cannot be null or 
blank"));
+  }
+
+  @Test
+  void checkReportsAWhitespaceFolderName() {
+    ActionCreateFolder action = new ActionCreateFolder();
+    action.setFolderName("   ");
+
+    List<String> errors = errors(check(action));
+
+    assertEquals(1, errors.size());
+    assertTrue(errors.getFirst().contains("folderName cannot be null or 
blank"));
+  }
+
+  @Test
+  void executeFailsWhenNoFolderNameIsDefined() {
+    ActionCreateFolder action = new ActionCreateFolder();
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.isResult());
+    assertEquals(0, result.getNrErrors());
+  }
+
+  @Test
+  void executeCreatesAMissingFolder() {
+    ActionCreateFolder action = new ActionCreateFolder();
+    Path folder = tempDir.resolve("created");
+    action.setFolderName(folder.toString());
+
+    Result result = action.execute(new Result(), 0);
+
+    assertTrue(result.isResult());
+    assertEquals(0, result.getNrErrors());
+    assertTrue(Files.isDirectory(folder));
+  }
+
+  @Test
+  void executeFailsWhenTheFolderAlreadyExists() throws Exception {
+    ActionCreateFolder action = new ActionCreateFolder();
+    Path folder = Files.createDirectory(tempDir.resolve("exists"));
+    action.setFolderName(folder.toString());
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.isResult());
+    assertEquals(0, result.getNrErrors());
+  }
+
+  @Test
+  void executeSucceedsWhenAnExistingFolderIsAllowed() throws Exception {
+    ActionCreateFolder action = new ActionCreateFolder();
+    Path folder = Files.createDirectory(tempDir.resolve("exists"));
+    action.setFolderName(folder.toString());
+    action.setFailIfFolderExists(false);
+
+    Result result = action.execute(new Result(), 0);
+
+    assertTrue(result.isResult());
+    assertEquals(0, result.getNrErrors());
+  }
+
+  @Test
+  void executeFailsWhenAFileOccupiesTheFolderName() throws Exception {
+    ActionCreateFolder action = new ActionCreateFolder();
+    Path file = Files.createFile(tempDir.resolve("not-a-folder"));
+    action.setFolderName(file.toString());
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.isResult());
+    assertEquals(0, result.getNrErrors());
+  }
+
+  @Test
+  void executeReportsAnErrorWhenTheFolderCannotBeCreated() throws Exception {
+    ActionCreateFolder action = new ActionCreateFolder();
+    Path file = Files.createFile(tempDir.resolve("parent-is-a-file"));
+    action.setFolderName(file.resolve("child").toString());
+
+    Result result = action.execute(new Result(), 0);
+
+    assertFalse(result.isResult());
+    assertEquals(1, result.getNrErrors());
+  }
+
+  private static List<ICheckResult> check(ActionCreateFolder action) {
+    List<ICheckResult> remarks = new ArrayList<>();
+    action.check(remarks, null, action, null);
+    return remarks;
+  }
+
+  private static List<String> errors(List<ICheckResult> remarks) {
+    List<String> errors = new ArrayList<>();
+    for (ICheckResult remark : remarks) {
+      if (remark.getType() == ICheckResult.TYPE_RESULT_ERROR) {
+        errors.add(remark.getText());
+      }
+    }
+    return errors;
+  }
 }

Reply via email to