This is an automated email from the ASF dual-hosted git repository.
mattcasters 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 839ff52c67 issue #7516 : fix integration tests broken by single-JVM
runner (#7517)
839ff52c67 is described below
commit 839ff52c672dabba915f1afc9f9dde48e6503e3a
Author: Matt Casters <[email protected]>
AuthorDate: Mon Jul 13 20:04:13 2026 +0200
issue #7516 : fix integration tests broken by single-JVM runner (#7517)
Preserve project/environment variables when hop-run starts a pipeline
(do not re-initialize from null after the factory already applied them).
Prefer existing variables over empty parameter defaults on activate, and
pass parent variables into nested workflow parameters. Use hop-local for
the suite runner on Beam projects, configure AES2 encoder in the aes IT
project, and update 0083 expected WorkflowExecutor execution-result fields.
---
.../hop/core/parameters/NamedParameters.java | 15 +++++++++--
.../core/parameters/NamedParamsDefaultTest.java | 30 ++++++++++++++++++++++
.../main/java/org/apache/hop/run/HopRunBase.java | 5 +++-
integration-tests/aes/dev-env-config.json | 8 ++++++
integration-tests/aes/hop-config.json | 4 +--
integration-tests/scripts/run-tests.sh | 18 ++++++++++---
.../transforms/0083-workflow-executor-run-wf.hpl | 2 +-
.../workflow/actions/pipeline/ActionPipeline.java | 3 ++-
.../workflow/actions/workflow/ActionWorkflow.java | 8 ++++++
9 files changed, 82 insertions(+), 11 deletions(-)
diff --git
a/core/src/main/java/org/apache/hop/core/parameters/NamedParameters.java
b/core/src/main/java/org/apache/hop/core/parameters/NamedParameters.java
index 2bda141187..24c341dcc6 100644
--- a/core/src/main/java/org/apache/hop/core/parameters/NamedParameters.java
+++ b/core/src/main/java/org/apache/hop/core/parameters/NamedParameters.java
@@ -137,8 +137,19 @@ public class NamedParameters implements INamedParameters {
public void activateParameters(IVariables variables) {
for (NamedParameter param : params.values()) {
if (StringUtils.isNotEmpty(param.key)) {
- variables.setVariable(
- param.getKey(), Const.NVL(param.getValue(),
Const.NVL(param.getDefaultValue(), "")));
+ String value = param.getValue();
+ if (StringUtils.isEmpty(value)) {
+ // Prefer an already-set variable (environment / parent) over the
parameter default.
+ // Nested workflows and pipelines used to clobber env values such as
HOSTNAME or
+ // BOOTSTRAP_SERVERS when activateParameters applied empty defaults.
+ String existing = variables != null ?
variables.getVariable(param.getKey()) : null;
+ if (StringUtils.isNotEmpty(existing)) {
+ value = existing;
+ } else {
+ value = Const.NVL(param.getDefaultValue(), "");
+ }
+ }
+ variables.setVariable(param.getKey(), value);
}
}
}
diff --git
a/core/src/test/java/org/apache/hop/core/parameters/NamedParamsDefaultTest.java
b/core/src/test/java/org/apache/hop/core/parameters/NamedParamsDefaultTest.java
index fa050fc01a..252630fb1f 100644
---
a/core/src/test/java/org/apache/hop/core/parameters/NamedParamsDefaultTest.java
+++
b/core/src/test/java/org/apache/hop/core/parameters/NamedParamsDefaultTest.java
@@ -78,6 +78,36 @@ class NamedParamsDefaultTest {
assertEquals("CCC", variables.getVariable("var3"));
}
+ @Test
+ void testActivateParametersPrefersExistingVariableOverDefault() throws
Exception {
+ Variables variables = new Variables();
+ variables.setVariable("HOSTNAME", "http");
+ variables.setVariable("BOOTSTRAP_SERVERS", "kafka:9092");
+
+ namedParams.addParameterDefinition("HOSTNAME", "localhost", "HTTP host");
+ namedParams.addParameterDefinition("BOOTSTRAP_SERVERS", "", "Kafka
bootstrap");
+ namedParams.addParameterDefinition("ONLY_DEFAULT", "from-default", "No
prior variable");
+
+ namedParams.activateParameters(variables);
+
+ assertEquals("http", variables.getVariable("HOSTNAME"));
+ assertEquals("kafka:9092", variables.getVariable("BOOTSTRAP_SERVERS"));
+ assertEquals("from-default", variables.getVariable("ONLY_DEFAULT"));
+ }
+
+ @Test
+ void testActivateParametersExplicitValueWinsOverExistingVariable() throws
Exception {
+ Variables variables = new Variables();
+ variables.setVariable("HOSTNAME", "http");
+
+ namedParams.addParameterDefinition("HOSTNAME", "localhost", "HTTP host");
+ namedParams.setParameterValue("HOSTNAME", "explicit-host");
+
+ namedParams.activateParameters(variables);
+
+ assertEquals("explicit-host", variables.getVariable("HOSTNAME"));
+ }
+
@Test
void testAddParameterDefinitionWithException() throws
DuplicateParamException {
namedParams.addParameterDefinition("key", "value", "description");
diff --git a/engine/src/main/java/org/apache/hop/run/HopRunBase.java
b/engine/src/main/java/org/apache/hop/run/HopRunBase.java
index ebf6edb64c..7ce773bc8f 100644
--- a/engine/src/main/java/org/apache/hop/run/HopRunBase.java
+++ b/engine/src/main/java/org/apache/hop/run/HopRunBase.java
@@ -290,7 +290,10 @@ public abstract class HopRunBase implements Runnable,
IHasHopMetadataProvider {
PipelineEngineFactory.createPipelineEngine(
variables, pipelineRunConfigurationName, metadataProvider,
pipelineMeta);
pipeline.getPipelineMeta().setInternalHopVariables(pipeline);
- pipeline.initializeFrom(null);
+ // Do not call initializeFrom(null) here: the factory already
initialized the engine from
+ // hop-run's variables (project + environment). Re-initializing from
null would drop those
+ // values (e.g. HOSTNAME, TEST_0012) and only re-apply hop-config
defaults — breaking the
+ // single-JVM IT suite runner and any hop-run of a pipeline with -e.
List<EngineCompatibilityChecker.Violation> pipelineViolations =
EngineCompatibilityChecker.checkPipeline(pipelineMeta, pipeline);
diff --git a/integration-tests/aes/dev-env-config.json
b/integration-tests/aes/dev-env-config.json
index 09dfeb99fa..471c885669 100644
--- a/integration-tests/aes/dev-env-config.json
+++ b/integration-tests/aes/dev-env-config.json
@@ -3,5 +3,13 @@
"name" : "AES2_PASSWORD",
"value" : "AES2 5SPGXV3SEPhoDRiYIxBv+wtnSC7WQYoYU6zyJx1Y75sEzHAM",
"description" : ""
+ }, {
+ "name" : "HOP_PASSWORD_ENCODER_PLUGIN",
+ "value" : "AES2",
+ "description" : "AES2 encoder required to decrypt AES2_PASSWORD in this
suite"
+ }, {
+ "name" : "HOP_AES_ENCODER_KEY",
+ "value" : "abcdef",
+ "description" : "Key matching the ciphertext stored in AES2_PASSWORD"
} ]
}
\ No newline at end of file
diff --git a/integration-tests/aes/hop-config.json
b/integration-tests/aes/hop-config.json
index 8a188da4ab..064aa482fb 100644
--- a/integration-tests/aes/hop-config.json
+++ b/integration-tests/aes/hop-config.json
@@ -167,8 +167,8 @@
},
{
"name": "HOP_PASSWORD_ENCODER_PLUGIN",
- "value": "Hop",
- "description": "Specifies the password encoder plugin to use by ID (Hop
is the default)."
+ "value": "AES2",
+ "description": "AES2 encoder required by the aes integration-test
project (matches docker env)."
},
{
"name": "HOP_SYSTEM_HOSTNAME",
diff --git a/integration-tests/scripts/run-tests.sh
b/integration-tests/scripts/run-tests.sh
index c2072ca497..ccbbb8147a 100755
--- a/integration-tests/scripts/run-tests.sh
+++ b/integration-tests/scripts/run-tests.sh
@@ -137,9 +137,8 @@ TMP_CONFIG_FOLDER="${HOP_CONFIG_FOLDER}"
SUREFIRE_DIR="$(cd "${CURRENT_DIR}/../surefire-reports" && pwd)"
RUNNER_PIPELINE="${CURRENT_DIR}/run-project-tests.hpl"
-# Shared hop-run parameters for both single-JVM and per-test modes
+# Shared hop-run parameters for both single-JVM and per-test modes (run
configuration added per project)
HOP_RUN_COMMON_ARGS=(
- -r "local"
-e "dev"
-p "POSTGRES_HOST=${POSTGRES_HOST}"
-p "POSTGRES_DATABASE=${POSTGRES_DATABASE}"
@@ -180,16 +179,26 @@ for d in "${CURRENT_DIR}"/../${PROJECT_NAME}/; do
# Create New Project
export HOP_CONFIG_FOLDER="$d"
+ # Default pipeline run configuration name used by hop-run and the suite
runner.
+ # Beam projects name their Beam engine "local" and keep a native Local
engine as "hop-local".
+ # The single-JVM suite driver (run-project-tests.hpl) must never run
under Beam.
+ PIPELINE_RUN_CONFIG="local"
+ SUITE_RUN_CONFIG="local"
+ if [ -f "$d/metadata/pipeline-run-configuration/hop-local.json" ]; then
+ SUITE_RUN_CONFIG="hop-local"
+ fi
+
# Prefer single-JVM suite runner when available (unless isolation mode
is requested)
if [ "${HOP_IT_PER_TEST_JVM}" != "true" ] && [ -f "${RUNNER_PIPELINE}"
]; then
echo ${SPACER}
- echo "Running project tests in single JVM via run-project-tests.hpl"
+ echo "Running project tests in single JVM via run-project-tests.hpl
(run config: ${SUITE_RUN_CONFIG})"
echo ${SPACER}
start_time_test=$SECONDS
$HOP_LOCATION/hop-run.sh \
+ -r "${SUITE_RUN_CONFIG}" \
"${HOP_RUN_COMMON_ARGS[@]}" \
-p "PROJECT_NAME=${PROJECT_NAME}" \
-p "IT_SUREFIRE_DIR=${SUREFIRE_DIR}" \
@@ -252,8 +261,9 @@ for d in "${CURRENT_DIR}"/../${PROJECT_NAME}/; do
#Start time test
start_time_test=$SECONDS
- #Run Test
+ #Run Test (use project pipeline run config, e.g. Beam "local")
$HOP_LOCATION/hop-run.sh \
+ -r "${PIPELINE_RUN_CONFIG}" \
"${HOP_RUN_COMMON_ARGS[@]}" \
-f "$hop_file" > >(tee /tmp/test_output) 2> >(tee
/tmp/test_output_err >&1)
diff --git a/integration-tests/transforms/0083-workflow-executor-run-wf.hpl
b/integration-tests/transforms/0083-workflow-executor-run-wf.hpl
index a39c2379b9..d70a870c9c 100644
--- a/integration-tests/transforms/0083-workflow-executor-run-wf.hpl
+++ b/integration-tests/transforms/0083-workflow-executor-run-wf.hpl
@@ -115,7 +115,7 @@ limitations under the License.
<group/>
<length>-1</length>
<name>expected</name>
- <nullif>ExecutionTime, ExecutionResult, ExecutionNrErrors,
ExecutionLinesRead, ExecutionLinesWritten, ExecutionLinesInput,
ExecutionLinesOutput, ExecutionLinesRejected, ExecutionLinesUpdated,
ExecutionLinesDeleted, ExecutionFilesRetrieved, ExecutionExitStatus,
ExecutionLogText, ExecutionLogChannelId</nullif>
+ <nullif>f1, ExecutionTime, ExecutionResult, ExecutionNrErrors,
ExecutionLinesRead, ExecutionLinesWritten, ExecutionLinesInput,
ExecutionLinesOutput, ExecutionLinesRejected, ExecutionLinesUpdated,
ExecutionLinesDeleted, ExecutionFilesRetrieved, ExecutionExitStatus,
ExecutionLogText, ExecutionLogChannelId</nullif>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
<type>String</type>
diff --git
a/plugins/actions/pipeline/src/main/java/org/apache/hop/workflow/actions/pipeline/ActionPipeline.java
b/plugins/actions/pipeline/src/main/java/org/apache/hop/workflow/actions/pipeline/ActionPipeline.java
index 1201b5b004..55e4a52ba4 100644
---
a/plugins/actions/pipeline/src/main/java/org/apache/hop/workflow/actions/pipeline/ActionPipeline.java
+++
b/plugins/actions/pipeline/src/main/java/org/apache/hop/workflow/actions/pipeline/ActionPipeline.java
@@ -522,8 +522,9 @@ public class ActionPipeline extends ActionBase implements
Cloneable, IAction {
pipeline.setMetadataProvider(getMetadataProvider());
// Handle parameters...
+ // Factory already initialized the pipeline from this action's
variables (parent workflow
+ // + env). Do not re-initialize from null or environment variables are
dropped.
//
- pipeline.initializeFrom(null);
pipeline.copyParametersFromDefinitions(pipelineMeta);
// Pass the parameter values and activate...
diff --git
a/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
b/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
index 29807ab860..f26323b2b3 100644
---
a/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
+++
b/plugins/actions/workflow/src/main/java/org/apache/hop/workflow/actions/workflow/ActionWorkflow.java
@@ -479,6 +479,14 @@ public class ActionWorkflow extends ActionBase implements
Cloneable, IAction {
String parentValue =
parentWorkflow.getParameterValue(parameterName);
if (!Utils.isEmpty(parentValue)) {
workflow.setParameterValue(parameterName, parentValue);
+ } else {
+ // Match hop-run: if the parent has a variable of the same
name (env, -p as
+ // variable, project config), use it so nested main-*.hwf
parameters do not
+ // fall back to their local-dev defaults (e.g.
HOSTNAME=localhost).
+ String parentVariable =
parentWorkflow.getVariable(parameterName);
+ if (!Utils.isEmpty(parentVariable)) {
+ workflow.setParameterValue(parameterName, parentVariable);
+ }
}
}
}